OSDN Git Service

This commit was generated by cvs2svn to compensate for changes in r4,
[nucleus-jp/nucleus-jp-ancient.git] / euc / nucleus / libs / SKIN.php
1 <?php
2
3
4 /**
5   * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
6   * Copyright (C) 2002-2004 The Nucleus Group
7   *
8   * This program is free software; you can redistribute it and/or
9   * modify it under the terms of the GNU General Public License
10   * as published by the Free Software Foundation; either version 2
11   * of the License, or (at your option) any later version.
12   * (see nucleus/documentation/index.html#license for more info)
13   *
14   * Class representing a skin
15   *
16   * $Id: SKIN.php,v 1.1.1.1 2005-02-28 07:14:14 kimitake Exp $
17   */
18 class SKIN {
19
20         // after creating a SKIN object, evaluates to true when the skin exists
21         var $isValid;
22         
23         // skin characteristics. Use the getXXX methods rather than accessing directly
24         var $id;
25         var $description;
26         var $contentType;
27         var $includeMode;               // either 'normal' or 'skindir'
28         var $includePrefix;
29         var $name;
30         
31         function SKIN($id) {
32                 $this->id = intval($id);
33
34                 // read skin name/description/content type
35                 $res = sql_query('SELECT * FROM '.sql_table('skin_desc').' WHERE sdnumber=' . $this->id);
36                 $obj = mysql_fetch_object($res);
37                 $this->isValid = (mysql_num_rows($res) > 0);
38                 if (!$this->isValid)
39                         return;
40                         
41                 $this->name = $obj->sdname;
42                 $this->description = $obj->sddesc;
43                 $this->contentType = $obj->sdtype;
44                 $this->includeMode = $obj->sdincmode;
45                 $this->includePrefix = $obj->sdincpref;
46
47         }
48         
49         function getID() {                              return $this->id; }
50         function getName() {                    return $this->name; }
51         function getDescription() {     return $this->description; }
52         function getContentType() {     return $this->contentType; }
53         function getIncludeMode() {     return $this->includeMode; }
54         function getIncludePrefix() {   return $this->includePrefix; }
55         
56         // returns true if there is a skin with the given shortname (static)
57         function exists($name) {
58                 return quickQuery('select count(*) as result FROM '.sql_table('skin_desc').' WHERE sdname="'.addslashes($name).'"') > 0;
59         }
60
61         // returns true if there is a skin with the given ID (static)
62         function existsID($id) {
63                 return quickQuery('select COUNT(*) as result FROM '.sql_table('skin_desc').' WHERE sdnumber='.intval($id)) > 0;
64         }       
65         
66         // (static)
67         function createFromName($name) {
68                 return new SKIN(SKIN::getIdFromName($name));
69         }       
70         
71         // (static)
72         function getIdFromName($name) {
73                 $query =  'SELECT sdnumber'
74                        . ' FROM '.sql_table('skin_desc')
75                        . ' WHERE sdname="'.addslashes($name).'"';
76                 $res = sql_query($query);
77                 $obj = mysql_fetch_object($res);
78                 return $obj->sdnumber;  
79         }
80         
81         // (static)
82         function getNameFromId($id) {
83                 return quickQuery('SELECT sdname as result FROM '.sql_table('skin_desc').' WHERE sdnumber=' . intval($id));
84         }
85         
86         /**
87          * Creates a new skin, with the given characteristics.
88          *
89          * (static)
90          */
91         function createNew($name, $desc, $type = 'text/html', $includeMode = 'normal', $includePrefix = '') {
92                 global $manager;
93                 
94                 $manager->notify(
95                         'PreAddSkin',
96                         array(
97                                 'name' => &$name,
98                                 'description' => &$desc,
99                                 'type' => &$type,
100                                 'includeMode' => &$includeMode,
101                                 'includePrefix' => &$includePrefix
102                         )
103                 );
104
105                 sql_query('INSERT INTO '.sql_table('skin_desc')." (sdname, sddesc, sdtype, sdincmode, sdincpref) VALUES ('" . addslashes($name) . "','" . addslashes($desc) . "','".addslashes($type)."','".addslashes($includeMode)."','".addslashes($includePrefix)."')");
106                 $newid = mysql_insert_id();
107                 
108                 $manager->notify(
109                         'PostAddSkin',
110                         array(
111                                 'skinid' => $newid,
112                                 'name' => $name,
113                                 'description' => $desc,
114                                 'type' => $type,
115                                 'includeMode' => $includeMode,
116                                 'includePrefix' => $includePrefix
117                         )
118                 );
119                 
120                 return $newid;
121         }
122         
123         function parse($type) {
124                 global $manager, $CONF;
125
126                 // set output type
127                 sendContentType($this->getContentType(), 'skin', _CHARSET);
128
129                 // set skin name as global var (so plugins can access it)
130                 global $currentSkinName;
131                 $currentSkinName = $this->getName();
132
133                 $contents = $this->getContent($type);
134
135                 if (!$contents) {
136                         // use base skin if this skin does not have contents
137                         $defskin =& new SKIN($CONF['BaseSkin']);
138                         $contents = $defskin->getContent($type);
139                         if (!$contents) {
140                                 echo _ERROR_SKIN;
141                                 return;
142                         }
143                 }
144
145                 $actions = $this->getAllowedActionsForType($type);
146
147                 $manager->notify('PreSkinParse',array('skin' => &$this, 'type' => $type));
148
149                 // set IncludeMode properties of parser
150                 PARSER::setProperty('IncludeMode',$this->getIncludeMode());
151                 PARSER::setProperty('IncludePrefix',$this->getIncludePrefix());
152
153                 $handler =& new ACTIONS($type, $this);
154                 $parser =& new PARSER($actions, $handler);
155                 $handler->setParser($parser);
156                 $handler->setSkin($this);
157                 $parser->parse($contents);
158
159                 $manager->notify('PostSkinParse',array('skin' => &$this, 'type' => $type));
160
161
162         }
163
164         function getContent($type) {
165                 $query = 'SELECT scontent FROM '.sql_table('skin')." WHERE sdesc=$this->id and stype='". addslashes($type) ."'";
166                 $res = sql_query($query);
167
168                 if (mysql_num_rows($res) == 0)
169                         return '';
170                 else
171                         return mysql_result($res, 0, 0);
172         }
173
174         /**
175          * Updates the contents of one part of the skin
176          */
177         function update($type, $content) {
178                 $skinid = $this->id;
179                 $content = trim($content);
180
181                 // delete old thingie
182                 sql_query('DELETE FROM '.sql_table('skin')." WHERE stype='".addslashes($type)."' and sdesc=" . intval($skinid));
183
184                 // write new thingie
185                 if ($content) {
186                         sql_query('INSERT INTO '.sql_table('skin')." SET scontent='" . addslashes($content) . "', stype='" . addslashes($type) . "', sdesc=" . intval($skinid));
187                 }       
188         }
189         
190         /**
191          * Deletes all skin parts from the database
192          */
193         function deleteAllParts() {
194                 sql_query('DELETE FROM '.sql_table('skin').' WHERE sdesc='.$this->getID());
195         }
196         
197         /**
198          * Updates the general information about the skin
199          */
200         function updateGeneralInfo($name, $desc, $type = 'text/html', $includeMode = 'normal', $includePrefix = '') {
201                 $query =  'UPDATE '.sql_table('skin_desc').' SET'
202                        . " sdname='" . addslashes($name) . "',"
203                        . " sddesc='" . addslashes($desc) . "',"
204                        . " sdtype='" . addslashes($type) . "',"
205                            . " sdincmode='" . addslashes($includeMode) . "',"
206                            . " sdincpref='" . addslashes($includePrefix) . "'"                 
207                        . " WHERE sdnumber=" . $this->getID();
208                 sql_query($query);              
209         }
210         
211         /**
212          * static: returns an array of friendly names
213          */
214         function getFriendlyNames() {
215                 return array(
216                         'index' => _SKIN_PART_MAIN,
217                         'item' => _SKIN_PART_ITEM,
218                         'archivelist' => _SKIN_PART_ALIST,
219                         'archive' => _SKIN_PART_ARCHIVE,
220                         'search' => _SKIN_PART_SEARCH,
221                         'error' => _SKIN_PART_ERROR,
222                         'member' => _SKIN_PART_MEMBER,
223                         'imagepopup' => _SKIN_PART_POPUP
224                 );      
225         }
226         
227         function getAllowedActionsForType($type) {
228                 // some actions that can be performed at any time, from anywhere
229                 $defaultActions = array('otherblog',
230                                                                 'plugin',
231                                                                 'version',
232                                                                 'nucleusbutton',
233                                                                 'include',
234                                                                 'phpinclude',
235                                                                 'parsedinclude',
236                                                                 'loginform',
237                                                                 'sitevar',
238                                                                 'otherarchivelist',
239                                                                 'otherarchivedaylist',
240                                                                 'self',
241                                                                 'adminurl',
242                                                                 'todaylink',
243                                                                 'archivelink',
244                                                                 'member',
245                                                                 'ifcat',                                        // deprecated (Nucleus v2.0)
246                                                                 'category',
247                                                                 'searchform',
248                                                                 'referer',
249                                                                 'skinname',
250                                                                 'skinfile',
251                                                                 'set',
252                                                                 'if',
253                                                                 'else',
254                                                                 'endif'
255                                                                 );
256                 
257                 // extra actions specific for a certain skin type
258                 $extraActions = array();
259
260                 switch ($type) {
261                         case 'index':
262                                 $extraActions = array('blog', 
263                                                     'blogsetting',
264                                                     'preview',
265                                                     'additemform',
266                                                                 'categorylist',                                             
267                                                     'archivelist',
268                                                     'archivedaylist',
269                                                     'nextlink',
270                                                     'prevlink'
271                                                     );                          
272                                 break;
273                         case 'archive':
274                                 $extraActions = array('blog',
275                                                                 'archive',
276                                                                 'otherarchive',
277                                                                 'categorylist',                                                         
278                                                                 'archivelist',
279                                                     'archivedaylist',                                                           
280                                                                 'blogsetting',
281                                                                 'archivedate',
282                                                             'nextarchive',
283                                                             'prevarchive',
284                                                             'nextlink',
285                                                             'prevlink',
286                                                             'archivetype'
287                                 );
288                                 break;
289                         case 'archivelist':
290                                 $extraActions = array('blog',
291                                                             'archivelist',
292                                                                 'archivedaylist',
293                                                                 'categorylist',
294                                                             'blogsetting',
295                                                            );
296                                 break;
297                         case 'search':
298                                 $extraActions = array('blog',
299                                                                 'archivelist',
300                                                     'archivedaylist',
301                                                                 'categorylist',
302                                                                 'searchresults',
303                                                                 'othersearchresults',
304                                                                 'blogsetting',
305                                                                 'query',
306                                                                 'nextlink',
307                                                                 'prevlink'
308                                                                 );
309                                 break;
310                         case 'imagepopup':
311                                 $extraActions = array('image',
312                                                                 'imagetext',                            // deprecated (Nucleus v2.0)
313                                                                 );
314                                 break;
315                         case 'member':
316                                 $extraActions = array(
317                                                                 'membermailform',
318                                                                 'blogsetting',
319                                                                 'nucleusbutton'
320                                 );
321                                 break;
322                         case 'item':
323                                 $extraActions = array('blog',
324                                                             'item',
325                                                             'comments',
326                                                             'commentform',
327                                                             'vars',
328                                                             'blogsetting',
329                                                             'nextitem',
330                                                             'previtem',
331                                                             'nextlink',
332                                                             'prevlink',
333                                                             'nextitemtitle',
334                                                             'previtemtitle',
335                                                                 'categorylist',                                                     
336                                                             'archivelist',
337                                                     'archivedaylist',                                                       
338                                                             'itemtitle',
339                                                             'itemid',
340                                                             'itemlink',
341                                                             );
342                                 break;
343                         case 'error':
344                                 $extraActions = array(
345                                                                 'errormessage'
346                                 );
347                                 break;
348                 }
349                 return array_merge($defaultActions, $extraActions);
350         }
351         
352 }
353
354
355 /*
356  * This class contains the functions that get called by using
357  * the special tags in the skins
358  *
359  * The allowed tags for a type of skinpart are defined by the 
360  * SKIN::getAllowedActionsForType($type) method
361  */
362 class ACTIONS extends BaseActions {
363
364         // part of the skin currently being parsed ('index', 'item', 'archive',
365         // 'archivelist', 'member', 'search', 'error', 'imagepopup')
366         var $skintype;
367         
368         // contains an assoc array with parameters that need to be included when
369         // generating links to items/archives/... (e.g. catid)  
370         var $linkparams;
371         
372         // reference to the skin object for which a part is being parsed
373         var $skin;
374         
375
376         // used when including templated forms from the include/ dir. The $formdata var 
377         // contains the values to fill out in there (assoc array name -> value)
378         var $formdata;
379         
380
381         // filled out with the number of displayed items after calling one of the 
382
383         // (other)blog/(other)searchresults skinvars.
384
385         var $amountfound;
386
387         function ACTIONS($type) {
388                 // call constructor of superclass first
389                 $this->BaseActions();
390
391                 $this->skintype = $type;
392
393                 global $catid;
394                 if ($catid) 
395                         $this->linkparams = array('catid' => $catid);
396         }
397
398         function setSkin(&$skin) {
399                 $this->skin =& $skin;
400         }
401         
402         function setParser(&$parser) {
403                 $this->parser =& $parser;
404         }
405         
406         /*
407                 Forms get parsedincluded now, using an extra <formdata> skinvar
408         */
409         function doForm($filename) {
410                 global $DIR_NUCLEUS;
411                 array_push($this->parser->actions,'formdata','text','callback','errordiv');
412                 $oldIncludeMode = PARSER::getProperty('IncludeMode');
413                 $oldIncludePrefix = PARSER::getProperty('IncludePrefix');
414                 PARSER::setProperty('IncludeMode','normal');
415                 PARSER::setProperty('IncludePrefix','');
416                 $this->parse_parsedinclude($DIR_NUCLEUS . 'forms/' . $filename . '.template');
417                 PARSER::setProperty('IncludeMode',$oldIncludeMode);
418                 PARSER::setProperty('IncludePrefix',$oldIncludePrefix);
419                 array_pop($this->parser->actions);              // errordiv
420                 array_pop($this->parser->actions);              // callback
421                 array_pop($this->parser->actions);              // text
422                 array_pop($this->parser->actions);              // formdata
423         }
424         function parse_formdata($what) {
425                 echo $this->formdata[$what];
426         }
427         function parse_text($which) {
428                 // constant($which) only available from 4.0.4 :(
429                 if (defined($which)) {  
430                         eval("echo $which;");
431                 }
432         }
433         function parse_callback($eventName, $type)
434         {
435                 global $manager;
436                 $manager->notify($eventName, array('type' => $type));
437         }
438         function parse_errordiv() {
439                 global $errormessage;
440                 if ($errormessage)
441                         echo '<div class="error">', htmlspecialchars($errormessage),'</div>';
442         }
443         
444         function parse_skinname() {
445                 echo $this->skin->getName();
446         }
447         
448         function parse_if($field, $name='', $value = '') {
449                 global $catid, $blog, $member, $itemidnext, $itemidprev, $manager;
450
451                 $condition = 0;
452                 switch($field) {
453                         case 'category':
454                                 $condition = ($blog && $blog->isValidCategory($catid));
455                                 break;
456                         case 'blogsetting':
457                                 if ($name == 'trackback') {
458                                         $plugin =& $manager->getPlugin('NP_TrackBack');
459                                         if ($plugin != NULL){
460                                                 $bid = $blog->getID();
461                                                 if ($value === '1') $value = 'yes';
462                                                 if ($value === '0') $value = 'no';
463                                                 if ($plugin->getOption('AcceptPing') == 'no' ) {
464                                                         $condition = ($value == 'no');
465                                                         } else {
466                                                         $tb_option = $plugin->getBlogOption($bid,'AllowTrackBack');
467                                                         if (!$tb_option) {
468                                                                 $condition = ($value == 'yes');
469                                                         } else {
470                                                                 $condition = ($tb_option == $value);
471                                                         }
472                                                 }
473                                         }
474                                         break;
475                                 }
476                                 $condition = ($blog && ($blog->getSetting($name) == $value));
477                                 break;
478                         case 'loggedin':
479                                 $condition = $member->isLoggedIn();
480                                 break;
481                         case 'onteam':
482                                 $condition = $member->isLoggedIn() && $this->_ifOnTeam($name);
483                                 break;
484                         case 'admin':
485                                 $condition = $member->isLoggedIn() && $this->_ifAdmin($name);
486                                 break;                          
487                         case 'nextitem':
488                                 $condition = ($itemidnext != '');
489                                 break;
490                         case 'previtem':
491                                 $condition = ($itemidprev != ''); 
492                                 break;
493                         case 'skintype':
494                                 $condition = ($name == $this->skintype);
495                                 break;
496                         /*
497                                 hasplugin,PlugName
498                                         -> checks if plugin exists
499                                 hasplugin,PlugName,OptionName
500                                         -> checks if the option OptionName from plugin PlugName is not set to 'no'
501                                 hasplugin,PlugName,OptionName=value
502                                         -> checks if the option OptionName from plugin PlugName is set to value
503                         */
504                         case 'hasplugin':
505                 $condition = false;
506                 // (pluginInstalled method won't write a message in the actionlog on failure)
507                 if ($manager->pluginInstalled('NP_'.$name)) 
508                 {
509                                         $plugin =& $manager->getPlugin('NP_' . $name);
510                                         if ($plugin != NULL){
511                                                 if ($value == "") {
512                                                         $condition = true;
513                                                 } else {
514                                                         list($name2, $value2) = explode('=', $value, 2);
515                                                         if ($value2 == "" && $plugin->getOption($name2) != 'no') {
516                                                                 $condition = true;
517                                                         } else if ($plugin->getOption($name2) == $value2) {
518                                                                 $condition = true;
519                                                         }
520                                                 }
521                                         }
522                 }
523                 break;                          
524                         default:        
525                                 return;
526                 }
527                 $this->_addIfCondition($condition);
528         }
529         
530         function _ifOnTeam($blogName = '') {
531                 global $blog, $member, $manager;
532                 
533                 // when no blog found
534                 if (($blogName == '') && (!is_object($blog)))
535                         return 0;
536                 
537                 // explicit blog selection
538                 if ($blogName != '') 
539                         $blogid = getBlogIDFromName($blogName); 
540                 
541                 if (($blogName == '') || !$manager->existsBlogID($blogid))
542                         // use current blog
543                         $blogid = $blog->getID();
544                         
545                 return $member->teamRights($blogid);
546         }
547         
548         function _ifAdmin($blogName = '') {
549                 global $blog, $member, $manager;
550
551                 // when no blog found
552                 if (($blogName == '') && (!is_object($blog)))
553                         return 0;
554
555                 // explicit blog selection
556                 if ($blogName != '')
557                         $blogid = getBlogIDFromName($blogName);
558
559                 if (($blogName == '') || !$manager->existsBlogID($blogid))
560                         // use current blog
561                         $blogid = $blog->getID();
562
563                 return $member->isBlogAdmin($blogid);
564         }       
565         
566         function parse_ifcat($text = '') {
567                 if ($text == '') {
568                         // new behaviour
569                         $this->parse_if('category');
570                 } else {
571                         // old behaviour
572                         global $catid, $blog;
573                         if ($blog->isValidCategory($catid))
574                                 echo $text;
575                 }
576         }
577         
578         // a link to the today page (depending on selected blog, etc...)
579         function parse_todaylink($linktext = '') {
580                 global $blog, $CONF;
581                 if ($blog)
582                         echo $this->_link(createBlogidLink($blog->getID(),$this->linkparams), $linktext);
583                 else
584                         echo $this->_link($CONF['SiteUrl'], $linktext);
585         }
586         
587         // a link to the archives for the current blog (or for default blog)
588         function parse_archivelink($linktext = '') {
589                 global $blog, $CONF;
590                 if ($blog)
591                         echo $this->_link(createArchiveListLink($blog->getID(),$this->linkparams), $linktext);
592                 else
593                         echo $this->_link(createArchiveListLink(), $linktext);
594         }
595
596         // include itemid of prev item
597         function parse_previtem() {
598                 global $itemidprev;
599                 echo $itemidprev;
600         }
601
602         // include itemtitle of prev item
603         function parse_previtemtitle() {
604                 global $itemtitleprev;
605                 echo htmlspecialchars($itemtitleprev);
606         }
607
608         // include itemid of next item
609         function parse_nextitem() {
610                 global $itemidnext;
611                 echo $itemidnext;
612         }
613
614         // include itemtitle of next item
615         function parse_nextitemtitle() {
616                 global $itemtitlenext;
617                 echo htmlspecialchars($itemtitlenext);
618         }
619
620         function parse_prevarchive() {
621                 global $archiveprev;
622                 echo $archiveprev;
623         }
624
625         function parse_nextarchive() {
626                 global $archivenext;
627                 echo $archivenext;
628         }
629
630         function parse_archivetype() {
631                 global $archivetype;
632                 echo $archivetype;
633         }
634
635         function parse_prevlink($linktext = '', $amount = 10) {
636                 global $itemidprev, $archiveprev, $startpos;
637
638                 if ($this->skintype == 'item')
639                         $this->_itemlink($itemidprev, $linktext);
640             else if ($this->skintype == 'search' || $this->skintype == 'index')
641                 $this->_searchlink($amount, $startpos, 'prev', $linktext);
642                 else
643                         $this->_archivelink($archiveprev, $linktext);
644         }
645         
646         function parse_nextlink($linktext = '', $amount = 10) {
647                 global $itemidnext, $archivenext, $startpos;
648                 if ($this->skintype == 'item')
649                         $this->_itemlink($itemidnext, $linktext);
650             else if ($this->skintype == 'search' || $this->skintype == 'index')
651                 $this->_searchlink($amount, $startpos, 'next', $linktext);
652                 else
653                         $this->_archivelink($archivenext, $linktext);
654         }
655         
656         /**
657          * returns either
658          *              - a raw link (html/xml encoded) when no linktext is provided
659          *              - a (x)html <a href... link when a text is present (text htmlencoded)
660          */
661         function _link($url, $linktext = '')
662         {
663                 $u = htmlspecialchars($url);
664                 $u = preg_replace("/&amp;amp;/",'&amp;',$u); // fix URLs that already had encoded ampersands
665                 if ($linktext != '')
666                         $l = '<a href="' . $u .'">'.htmlspecialchars($linktext).'</a>';
667                 else
668                         $l = $u;
669                 return $l;      
670         }
671
672         /**
673          * Outputs a next/prev link
674          *
675          * @param $maxresults
676          *              The maximum amount of items shown per page (e.g. 10)
677          * @param $startpos
678          *              Current start position (requestVar('startpos'))
679          * @param $direction
680          *              either 'prev' or 'next'
681          * @param $linktext
682          *              When present, the output will be a full <a href...> link. When empty,
683          *              only a raw link will be outputted
684          */
685     function _searchlink($maxresults, $startpos, $direction, $linktext = '') {
686         global $CONF, $blog, $query, $amount;
687         // TODO: Move request uri to linkparams. this is ugly. sorry for that.
688         $startpos       = intval($startpos);            // will be 0 when empty. 
689         $parsed         = parse_url(serverVar('REQUEST_URI'));
690         $parsed         = $parsed['query'];
691                 $url            = '';
692         
693         switch ($direction) {
694             case 'prev':
695                 if ( intval($startpos) - intval($maxresults) >= 0) {
696                     $startpos   = intval($startpos) - intval($maxresults);
697                     $url                = $CONF['SearchURL'].'?'.alterQueryStr($parsed,'startpos',$startpos);
698                 }
699                 break;
700             case 'next':
701                 $iAmountOnPage = $this->amountfound;
702                 if ($iAmountOnPage == 0)
703                 {
704                         // [%nextlink%] or [%prevlink%] probably called before [%blog%] or [%searchresults%]
705                         // try a count query
706                         switch ($this->skintype)
707                         {
708                                 case 'index':
709                                         $sqlquery = $blog->getSqlBlog('', 'count');
710                                         break;
711                                 case 'search':
712                                         $sqlquery = $blog->getSqlSearch($query, $amount, $unused_highlight, 'count');
713                                         break;
714                         }
715                         if ($sqlquery) 
716                                 $iAmountOnPage = intval(quickQuery($sqlquery)) - intval($startpos);
717                 }
718                 if (intval($iAmountOnPage) >= intval($maxresults)) {
719                         $startpos       = intval($startpos) + intval($maxresults);                
720                         $url            = $CONF['SearchURL'].'?'.alterQueryStr($parsed,'startpos',$startpos);
721                 }
722                 break;
723             default:
724                 break;
725         } // switch($direction)
726
727                 if ($url != '')
728                         echo $this->_link($url, $linktext);        
729     }
730
731         function _itemlink($id, $linktext = '') {
732                 global $CONF;
733                 if ($id)
734                         echo $this->_link(createItemLink($id, $this->linkparams), $linktext);
735                 else
736                         $this->parse_todaylink($linktext);
737         }
738
739         function _archivelink($id, $linktext = '') {
740                 global $CONF, $blog;
741                 if ($id)
742                         echo $this->_link(createArchiveLink($blog->getID(), $id, $this->linkparams), $linktext);
743                 else
744                         $this->parse_todaylink($linktext);
745         }
746         
747         
748         function parse_itemlink($linktext = '') {       
749                 $this->_itemlink($itemid, $linktext);
750         }
751         
752         /**
753           * %archivedate(locale,date format)%
754           */
755         function parse_archivedate($locale = '-def-') {
756                 global $archive;
757                 
758                 if ($locale == '-def-')
759                         setlocale(LC_TIME,$template['LOCALE']);
760                 else
761                         setlocale(LC_TIME,$locale);
762                 
763                 // get archive date
764                 sscanf($archive,'%d-%d-%d',$y,$m,$d);
765
766                 // get format           
767                 $args = func_get_args();
768                 // format can be spread over multiple parameters
769                 if (sizeof($args) > 1) {
770                         // take away locale
771                         array_shift($args);
772                         // implode
773                         $format=implode(',',$args);
774                 } elseif ($d == 0) {
775                         $format = '%B %Y';      
776                 } else {
777                         $format = '%d %B %Y';   
778                 }
779                 
780                 echo strftime($format,mktime(0,0,0,$m,$d?$d:1,$y));             
781         }
782         
783         function parse_blog($template, $amount = 10, $category = '') {
784                 global $blog, $startpos;
785                 
786                 list($limit, $offset) = sscanf($amount, '%d(%d)');
787                 $this->_setBlogCategory($blog, $category);
788                 $this->_preBlogContent('blog',$blog);
789                 $this->amountfound = $blog->readLog($template, $limit, $offset, $startpos);
790                 $this->_postBlogContent('blog',$blog);
791         }
792
793         function parse_otherblog($blogname, $template, $amount = 10, $category = '') {
794                 global $manager;
795
796                 list($limit, $offset) = sscanf($amount, '%d(%d)');
797
798                 $b =& $manager->getBlog(getBlogIDFromName($blogname));
799                 $this->_setBlogCategory($b, $category);
800                 $this->_preBlogContent('otherblog',$b);
801                 $this->amountfound = $b->readLog($template, $limit, $offset);
802                 $this->_postBlogContent('otherblog',$b);
803         }
804
805         // include one item (no comments)
806         function parse_item($template) {
807                 global $blog, $itemid, $highlight;
808                 $this->_setBlogCategory($blog, '');     // need this to select default category
809                 $this->_preBlogContent('item',$blog);
810                 $r = $blog->showOneitem($itemid, $template, $highlight);
811                 if ($r == 0)
812                         echo _ERROR_NOSUCHITEM;
813                 $this->_postBlogContent('item',$blog);
814         }
815
816         function parse_itemid() {
817                 global $itemid;
818                 echo $itemid;
819         }
820
821
822         // include comments for one item
823         function parse_comments($template) {
824                 global $itemid, $manager, $blog, $highlight;
825                 $template =& $manager->getTemplate($template);
826
827                 // create parser object & action handler
828                 $actions =& new ITEMACTIONS($blog);
829                 $parser =& new PARSER($actions->getDefinedActions(),$actions);
830                 $actions->setTemplate($template);
831                 $actions->setParser($parser);
832                 $item = ITEM::getitem($itemid, 0, 0);
833                 $actions->setCurrentItem($item);
834
835                 $comments =& new COMMENTS($itemid);
836                 $comments->setItemActions($actions);
837                 $comments->showComments($template, -1, 1, $highlight);  // shows ALL comments
838         }
839
840         function parse_archive($template, $category = '') {
841                 global $blog, $archive;
842                 // can be used with either yyyy-mm or yyyy-mm-dd
843                 sscanf($archive,'%d-%d-%d',$y,$m,$d);
844                 $this->_setBlogCategory($blog, $category);
845                 $this->_preBlogContent('achive',$blog);
846                 $blog->showArchive($template, $y, $m, $d);
847                 $this->_postBlogContent('achive',$blog);
848
849         }
850
851         function parse_otherarchive($blogname, $template, $category = '') {
852                 global $archive, $manager;
853                 sscanf($archive,'%d-%d-%d',$y,$m,$d);
854                 $b =& $manager->getBlog(getBlogIDFromName($blogname));
855                 $this->_setBlogCategory($b, $category);
856                 $this->_preBlogContent('otherachive',$b);
857                 $b->showArchive($template, $y, $m, $d);
858                 $this->_postBlogContent('otherachive',$b);
859         }
860
861         function parse_archivelist($template, $category = 'all', $limit = 0) {
862                 global $blog;
863                 if ($category == 'all') $category = '';
864                 $this->_preBlogContent('archivelist',$blog);
865                 $this->_setBlogCategory($blog, $category);
866                 $blog->showArchiveList($template, 'month', $limit);
867                 $this->_postBlogContent('archivelist',$blog);
868         }
869
870         function parse_archivedaylist($template, $category = 'all', $limit = 0) {
871                 global $blog;
872                 if ($category == 'all') $category = '';
873                 $this->_preBlogContent('archivelist',$blog);
874                 $this->_setBlogCategory($blog, $category);
875                 $blog->showArchiveList($template, 'day', $limit);
876                 $this->_postBlogContent('archivelist',$blog);
877         }
878
879
880         function parse_itemtitle() {
881                 global $manager, $itemid;
882                 $item =& $manager->getItem($itemid,0,0);
883                 echo htmlspecialchars(strip_tags($item['title']));
884         }
885
886         function parse_categorylist($template, $blogname = '') {
887                 global $blog, $manager;
888
889                 if ($blogname == '') {
890                         $this->_preBlogContent('categorylist',$blog);
891                         $blog->showCategoryList($template);
892                         $this->_postBlogContent('categorylist',$blog);
893                 } else {
894                         $b =& $manager->getBlog(getBlogIDFromName($blogname));
895                         $this->_preBlogContent('categorylist',$b);
896                         $b->showCategoryList($template);
897                         $this->_postBlogContent('categorylist',$b);
898                 }
899         }
900
901         function parse_category($type = 'name') {
902                 global $catid, $blog;
903                 if (!$blog->isValidCategory($catid))
904                         return;
905
906                 switch($type) {
907                         case 'name':
908                                 echo $blog->getCategoryName($catid);
909                                 break;
910                         case 'desc':
911                                 echo $blog->getCategoryDesc($catid);
912                                 break;
913                         case 'id':
914                                 echo $catid;
915                                 break;
916                 }
917         }
918
919         function parse_otherarchivelist($blogname, $template, $category = 'all', $limit = 0) {
920                 global $manager;
921                 if ($category == 'all') $category = '';
922                 $b =& $manager->getBlog(getBlogIDFromName($blogname));
923                 $this->_setBlogCategory($b, $category);
924                 $this->_preBlogContent('otherarchivelist',$b);
925                 $b->showArchiveList($template, 'month', $limit);
926                 $this->_postBlogContent('otherarchivelist',$b);
927         }
928
929         function parse_otherarchivedaylist($blogname, $template, $category = 'all', $limit = 0) {
930                 global $manager;
931                 if ($category == 'all') $category = '';
932                 $b =& $manager->getBlog(getBlogIDFromName($blogname));
933                 $this->_setBlogCategory($b, $category);
934                 $this->_preBlogContent('otherarchivelist',$b);
935                 $b->showArchiveList($template, 'day', $limit);
936                 $this->_postBlogContent('otherarchivelist',$b);
937         }
938
939         function parse_searchresults($template, $maxresults = 50 ) {
940                 global $blog, $query, $amount, $startpos;
941
942                 $this->_setBlogCategory($blog, '');     // need this to select default category
943                 $this->_preBlogContent('searchresults',$blog);
944                 $this->amountfound = $blog->search($query, $template, $amount, $maxresults, $startpos);
945                 $this->_postBlogContent('searchresults',$blog);
946         }
947
948         function parse_othersearchresults($blogname, $template, $maxresults = 50) {
949                 global $query, $amount, $manager, $startpos;
950                 $b =& $manager->getBlog(getBlogIDFromName($blogname));
951                 $this->_setBlogCategory($b, '');        // need this to select default category
952                 $this->_preBlogContent('othersearchresults',$b);
953                 $b->search($query, $template, $amount, $maxresults, $startpos);
954                 $this->_postBlogContent('othersearchresults',$b);
955         }
956
957         // includes the search query
958         function parse_query() {
959                 global $query;
960                 echo htmlspecialchars($query);
961         }
962                         
963         // include nucleus versionnumber
964         function parse_version() {
965                 global $nucleus;
966                 echo 'Nucleus ' . $nucleus['version'];
967         }
968         
969
970         function parse_errormessage() {
971                 global $errormessage;
972                 echo $errormessage;
973         }
974
975
976         function parse_imagetext() {                    
977                 echo htmlspecialchars(requestVar('imagetext'));
978         }
979         
980         function parse_image($what = 'imgtag') {
981                 global $CONF;
982
983                 $imagetext      = htmlspecialchars(requestVar('imagetext'));
984                 $imagepopup = requestVar('imagepopup');
985                 $width          = requestVar('width');
986                 $height         = requestVar('height');
987                 $fullurl = $CONF['MediaURL'] . $imagepopup;
988                 
989                 switch($what)
990                 {
991                         case 'url':
992                                 echo $fullurl;
993                                 break;
994                         case 'width':
995                                 echo $width;
996                                 break;
997                         case 'height':
998                                 echo $height;
999                                 break;
1000                         case 'caption':
1001                         case 'text':                    
1002                                 echo $imagetext;
1003                                 break;
1004                         case 'imgtag':
1005                         default:
1006                                 echo "<img src=\"$fullurl\" width=\"$width\" height=\"$height\" alt=\"$imagetext\" />";
1007                                 break;
1008                 }
1009         }
1010         
1011         // When commentform is not used, to include a hidden field with itemid
1012         function parse_vars() {
1013                 global $itemid;
1014                 echo '<input type="hidden" name="itemid" value="'.$itemid.'" />';
1015         }
1016         
1017         // include a sitevar
1018         function parse_sitevar($which) {
1019                 global $CONF;
1020                 switch($which) {
1021                         case 'url':
1022                                 echo $CONF['IndexURL'];
1023                                 break;
1024                         case 'name':
1025                                 echo $CONF['SiteName'];
1026                                 break;
1027                         case 'admin':
1028                                 echo $CONF['AdminEmail'];
1029                                 break;
1030                         case 'adminurl':
1031                                 echo $CONF['AdminURL'];
1032                 }                       
1033         }
1034         
1035         // shortcut for admin url
1036         function parse_adminurl() { $this->parse_sitevar('adminurl'); }
1037         
1038         function parse_blogsetting($which) {
1039                 global $blog;
1040                 switch($which) {
1041                         case 'id':
1042                                 echo $blog->getID();
1043                                 break;
1044                         case 'url':
1045                                 echo $blog->getURL();
1046                                 break;
1047                         case 'name':
1048                                 echo $blog->getName();
1049                                 break;
1050                         case 'desc':
1051                                 echo $blog->getDescription();
1052                                 break;
1053                         case 'short':
1054                                 echo $blog->getShortName();
1055                                 break;                          
1056                 }       
1057         }
1058         
1059         // includes a member info thingie
1060         function parse_member($what) {
1061                 global $memberinfo, $member;
1062                 
1063                 // 1. only allow the member-details-page specific variables on member pages
1064                 if ($this->skintype == 'member') {
1065
1066                         switch($what) {
1067                                 case 'name':
1068                                         echo $memberinfo->getDisplayName();
1069                                         break;
1070                                 case 'realname':
1071                                         echo $memberinfo->getRealName();
1072                                         break;
1073                                 case 'notes':
1074                                         echo $memberinfo->getNotes();
1075                                         break;
1076                                 case 'url':
1077                                         echo $memberinfo->getURL();
1078                                         break;
1079                                 case 'email':
1080                                         echo $memberinfo->getEmail();
1081                                         break;
1082                                 case 'id':
1083                                         echo $memberinfo->getID();
1084                                         break;                                  
1085                         }       
1086                 }
1087                 
1088                 // 2. the next bunch of options is available everywhere, as long as the user is logged in
1089                 if ($member->isLoggedIn())
1090                 {
1091                         switch($what) {
1092                                 case 'yourname':
1093                                         echo $member->getDisplayName();
1094                                         break;
1095                                 case 'yourrealname':
1096                                         echo $member->getRealName();
1097                                         break;
1098                                 case 'yournotes':
1099                                         echo $member->getNotes();
1100                                         break;
1101                                 case 'yoururl':
1102                                         echo $member->getURL();
1103                                         break;
1104                                 case 'youremail':
1105                                         echo $member->getEmail();
1106                                         break;
1107                                 case 'yourid':
1108                                         echo $member->getID();
1109                                         break;                                                                  
1110                         }       
1111                 }
1112
1113         }
1114         
1115         function parse_preview($template) {
1116                 global $blog, $CONF, $manager;
1117                 
1118                 $template =& $manager->getTemplate($template);
1119                 $row['body'] = '<span id="prevbody"></span>';
1120                 $row['title'] = '<span id="prevtitle"></span>';
1121                 $row['more'] = '<span id="prevmore"></span>';
1122                 $row['itemlink'] = '';
1123                 $row['itemid'] = 0; $row['blogid'] = $blog->getID();
1124                 echo TEMPLATE::fill($template['ITEM_HEADER'],$row);
1125                 echo TEMPLATE::fill($template['ITEM'],$row);
1126                 echo TEMPLATE::fill($template['ITEM_FOOTER'],$row);
1127         }
1128         
1129         function parse_additemform() {
1130                 global $blog, $CONF;
1131                 $this->formdata = array(
1132                         'adminurl' => htmlspecialchars($CONF['AdminURL']),
1133                         'catid' => $blog->getDefaultCategory()
1134                 );
1135                 $blog->InsertJavaScriptInfo(); 
1136                 $this->doForm('additemform');
1137         }
1138
1139         /**
1140           * Executes a plugin skinvar
1141           *
1142           * @param pluginName name of plugin (without the NP_)
1143           * 
1144           * extra parameters can be added
1145           */
1146         function parse_plugin($pluginName) {
1147                 global $manager;
1148                 
1149                 // only continue when the plugin is really installed
1150                 if (!$manager->pluginInstalled('NP_' . $pluginName))
1151                         return;
1152                 
1153                 $plugin =& $manager->getPlugin('NP_' . $pluginName);
1154                 if (!$plugin) return;
1155
1156                 // get arguments
1157                 $params = func_get_args();
1158                 
1159                 // remove plugin name 
1160                 array_shift($params);
1161                 
1162                 // add skin type on front
1163                 array_unshift($params, $this->skintype);
1164                 
1165                 call_user_func_array(array(&$plugin,'doSkinVar'), $params);
1166         }
1167
1168                         
1169         function parse_commentform($destinationurl = '') {
1170                 global $blog, $itemid, $member, $CONF, $manager, $DIR_LIBS, $errormessage;
1171                 
1172                 // warn when trying to provide a actionurl (used to be a parameter in Nucleus <2.0)
1173                 if (stristr($destinationurl, 'action.php')) {
1174                         $args = func_get_args();
1175                         $destinationurl = $args[1];
1176                         ACTIONLOG::add(WARNING,'actionurl is not longer a parameter on commentform skinvars. Moved to be a global setting instead.');
1177                 }
1178                 
1179                 $actionurl = $CONF['ActionURL'];
1180                 
1181                 // if item is closed, show message and do nothing
1182                 $item =& $manager->getItem($itemid,0,0);
1183                 if ($item['closed'] || !$blog->commentsEnabled()) {
1184                         $this->doForm('commentform-closed');
1185                         return;
1186                 }
1187                 
1188                 if (!$destinationurl)
1189                         $destinationurl = createItemLink($itemid, $this->linkparams);
1190
1191                 // values to prefill
1192                 $user = cookieVar($CONF['CookiePrefix'] .'comment_user');
1193                 if (!$user) $user = postVar('user');
1194                 $userid = cookieVar($CONF['CookiePrefix'] .'comment_userid');
1195                 if (!$userid) $userid = postVar('userid');
1196                 $body = postVar('body');
1197                 
1198                 $this->formdata = array(
1199                         'destinationurl' => htmlspecialchars($destinationurl),
1200                         'actionurl' => htmlspecialchars($actionurl),
1201                         'itemid' => $itemid,
1202                         'user' => htmlspecialchars($user),
1203                         'userid' => htmlspecialchars($userid),                  
1204                         'body' => htmlspecialchars($body),                      
1205                         'membername' => $member->getDisplayName(),
1206                         'rememberchecked' => cookieVar($CONF['CookiePrefix'] .'comment_user')?'checked="checked"':''
1207                 );
1208                 
1209                 if (!$member->isLoggedIn()) {
1210                         $this->doForm('commentform-notloggedin');
1211                 } else {
1212                         $this->doForm('commentform-loggedin');          
1213                 }
1214         }
1215
1216         function parse_loginform() {
1217                 global $member, $CONF;
1218                 if (!$member->isLoggedIn()) {
1219                         $filename = 'loginform-notloggedin';
1220                         $this->formdata = array();
1221                 } else {
1222                         $filename = 'loginform-loggedin';
1223                         $this->formdata = array(
1224                                 'membername' => $member->getDisplayName(),
1225                         );
1226                 }
1227                 $this->doForm($filename);
1228         }       
1229         
1230         
1231         function parse_membermailform($rows = 10, $cols = 40, $desturl = '') {
1232                 global $member, $CONF, $memberid;
1233                 
1234                 if ($desturl == '') {
1235                         if ($CONF['URLMode'] == 'pathinfo')
1236                                 $desturl = createMemberLink($memberid);
1237                         else
1238                                 $desturl = $CONF['IndexURL'] . createMemberLink($memberid);                             
1239                 }
1240                         
1241                 $message = postVar('message');
1242                 $frommail = postVar('frommail');
1243                 
1244                 $this->formdata = array(
1245                         'url' => htmlspecialchars($desturl),
1246                         'actionurl' => htmlspecialchars($CONF['ActionURL']),
1247                         'memberid' => $memberid,
1248                         'rows' => $rows,
1249                         'cols' => $cols,
1250                         'message' => htmlspecialchars($message),
1251                         'frommail' => htmlspecialchars($frommail)
1252                 );
1253                 if ($member->isLoggedIn()) {
1254                         $this->doForm('membermailform-loggedin');
1255                 } else if ($CONF['NonmemberMail']) {
1256                         $this->doForm('membermailform-notloggedin');            
1257                 } else {
1258                         $this->doForm('membermailform-disallowed');             
1259                 }
1260
1261         }
1262
1263         function parse_searchform($blogname = '') {
1264                 global $CONF, $manager, $maxresults;
1265                 if ($blogname) {
1266                         $blog =& $manager->getBlog(getBlogIDFromName($blogname));
1267                 } else {
1268                         global $blog;
1269                 }
1270                 // use default blog when no blog is selected
1271                 $this->formdata = array(
1272                         'id' => $blog?$blog->getID():$CONF['DefaultBlog'],
1273                         'query' => htmlspecialchars(getVar('query')),
1274                 );
1275                 $this->doForm('searchform');
1276         }
1277
1278         function parse_nucleusbutton($imgurl = '',
1279                                                              $imgwidth = '85',
1280                                                              $imgheight = '31') {
1281                 global $CONF;
1282                 if ($imgurl == '') {
1283                         $imgurl = $CONF['AdminURL'] . 'nucleus.gif';
1284                 } else if (PARSER::getProperty('IncludeMode') == 'skindir'){
1285                         // when skindit IncludeMode is used: start from skindir
1286                         $imgurl = $CONF['SkinsURL'] . PARSER::getProperty('IncludePrefix') . $imgurl;
1287                 }
1288
1289                 $this->formdata = array(
1290                         'imgurl' => $imgurl,
1291                         'imgwidth' => $imgwidth,
1292                         'imgheight' => $imgheight,
1293                 );
1294                 $this->doForm('nucleusbutton');
1295         }
1296         
1297         function parse_self() {
1298                 global $CONF;
1299                 echo $CONF['Self'];
1300         }
1301         
1302         function parse_referer() {
1303                 echo htmlspecialchars(serverVar('HTTP_REFERER'));
1304         }
1305         
1306         /**
1307           * Helper function that sets the category that a blog will need to use 
1308           *
1309           * @param $blog
1310           *             An object of the blog class, passed by reference (we want to make changes to it)
1311           * @param $catname
1312           *             The name of the category to use
1313           */
1314         function _setBlogCategory(&$blog, $catname) {
1315                 global $catid;
1316                 if ($catname != '')
1317                         $blog->setSelectedCategoryByName($catname);
1318                 else
1319                         $blog->setSelectedCategory($catid);
1320         }
1321         
1322         function _preBlogContent($type, &$blog) {
1323                 global $manager;
1324                 $manager->notify('PreBlogContent',array('blog' => &$blog, 'type' => $type));
1325         }
1326
1327         function _postBlogContent($type, &$blog) {
1328                 global $manager;
1329                 $manager->notify('PostBlogContent',array('blog' => &$blog, 'type' => $type));
1330         }
1331
1332 }
1333
1334 ?>