OSDN Git Service

コードがバラバラだった部分をマージ
[nucleus-jp/nucleus-plugins.git] / NP_TagEX / trunk / NP_TagEX.php
1 <?php
2 /**
3  * NP_TagEX
4  * TAGGING PLUG-IN FOR NucleusCMS
5  * PHP versions 4 and 5
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * (see nucleus/documentation/index.html#license for more info)
12  * 
13  * @author     Original Author nakahara21
14  * @copyright  2005-2008 nakahara21
15  * @copyright  2006-2009 shizuki
16  * @license    http://www.gnu.org/licenses/gpl.txt
17  *             GNU GENERAL PUBLIC LICENSE Version 2, June 1991
18  * @version    0.73
19  * @version    $Id$
20  * @link       http://nakahara21.com
21  */
22 /**
23  * HISTORY
24  *
25  * 0.73 TemplateExtraFields for v3.40
26  * 0.72 clean up
27  * 0.71 fix flat TAG level
28  * 0.70 add Tag lebel css
29  * 0.67 fix style
30  * 0.65 clean up
31  * 0.64 modified createTagLink function
32  * 0.63 fix Magical code
33  * 0.62 add function doIf() for NucleusCMS version3.3
34  * 0.6  fix delete tags when item update(425)
35  *      mod scanExistTags function
36  *      mod get tagLink title
37  * 0.51 typo fix
38  * 0.5  TAG sort modified
39  * 0.43 fix URL generate
40  * 0.42 add URL selected tag check
41  * 0.41 security fix and add some trick
42  * 0.4  fixed bug: numlic only
43  * 0.3  fixed bug: delete action
44  * 0.2  supports and/or query
45  */
46
47 /**
48  * define table names using plugin
49  */
50 if (!defined('_TAGEX_TABLE_DEFINED')) {
51         define('_TAGEX_TABLE_DEFINED', 1);
52         define('_TAGEX_TABLE',         sql_table('plug_tagex'));
53         define('_TAGEX_KLIST_TABLE',   sql_table('plug_tagex_klist'));
54 }
55
56 /**
57  * NP_TagEX class
58  */
59 class NP_TagEX extends NucleusPlugin
60 {
61 /**
62  * NP_MultipleCategories installed ?
63  * @var bool
64  */
65 public $maURL;
66 /**
67  * NP_CustomURL installed ?
68  * @var bool
69  */
70 public $cuURL;
71
72 // {{{ getName()
73
74         /**
75          * get Plugin name
76          * @return string
77          */
78         function getName()
79         {
80                 return 'Tags Extension';
81         }
82
83         // }}}
84         // {{{ getAuthor()
85
86         /**
87          * get Plugin author
88          * @return string
89          */
90         function getAuthor()
91         {
92                 return 'nakahara21 + shizuki + Tucker + Cacher';
93         }
94
95         // }}}
96         // {{{ getURL()
97
98         /**
99          * get Plugin getting URL
100          * @return string
101          */
102         function getURL()
103         {
104                 return 'http://japan.nucleuscms.org/wiki/plugins:tagex';
105         }
106
107         // }}}
108         // {{{ getVersion()
109
110         /**
111          * get Plugin version
112          * @return string
113          */
114         function getVersion()
115         {
116                 return '0.72';
117         }
118
119         // }}}
120         // {{{ getDescription()
121
122         /**
123          * get Plugin Description
124          * @return string
125          */
126         function getDescription()
127         {
128                 return 'Tags Extension (for Japanese users)';
129         }
130
131         // }}}
132         // {{{ supportsFeature()
133
134         /**
135          * get Plugin supports Nucleus CORE feature
136          * @param string Nucleus CORE feature
137          * @return bool
138          */
139         function supportsFeature($what)
140         {
141                 switch ($what) {
142                         case 'SqlTablePrefix':
143                                 return 1;
144                         default:
145                                 return 0;
146                 }
147         }
148
149         // }}}
150         // {{{ install()
151
152         /**
153          * plugin install script
154          *
155          * Create plugin options
156          *
157          * 'And' template's class 'tagex_and_or' CSS example
158          * tagex_and_or {
159          *     font-family:tahoma;
160          *     font-size:smaller;
161          * }
162          *
163          * 'TagIndex' template is 'taglevel' class ver. for default.
164          * But there use '<%fontlevel%>' template tag.
165          * For ex.
166          * <%and%><%or%>
167          * <span style="font-size:<%fontlevel%>em" title="<%tagamount%> post(s)! <%tagitems%>">
168          *     <a href="<%taglinkurl%>"><%tag%></a>
169          * </span>
170          */
171         function install()
172         {
173                 $tplAND = <<<__ANDTAGTPL__
174 <span class="tagex_and_or"> <a href="<%andurl%>" title="narrow">&amp;</a>.
175 __ANDTAGTPL__;
176                 $tplOR  = <<<__ORTAGTPL__
177 <a href="<%orurl%>" title="expand">or</a> </span>
178 __ORTAGTPL__;
179                 $tplIDX = <<<__ORTAGTPL__
180 <%and%><%or%>
181 <span class="level<%taglevel%>" title="<%tagamount%> post(s) <%tagitems%>">
182         <a href="<%taglinkurl%>"><%tag%></a>
183 </span>
184 __ORTAGTPL__;
185                 $this->createOption('flg_erase',         _NPTAGEX_ERASE_FLG,    'yesno',    'no');
186                 $this->createOption('editTagOrder',      _NPTAGEX_EDT_TAGORDER, 'select',   '1', _NPTAGEX_ORDER_VALUE);
187                 $this->createOption('and',               _NPTAGEX_TPL_AND,      'textarea', $tplAND);
188                 $this->createOption('or',                _NPTAGEX_TPL_OR,       'textarea', $tplOR);
189                 $this->createOption('tagIndex',          _NPTAGEX_TPL_TAGIDX,   'textarea', $tplIDX);
190                 $this->createOption('tagItemHeader',     _NPTAGEX_TPL_ITEMHEAD, 'textarea', '');
191                 $this->createOption('tagItem',           _NPTAGEX_TPL_TAGITEMS, 'textarea', '<%itemid%>:<%itemtitle%>');
192                 $this->createOption('tagItemSeparator',  _NPTAGEX_TPL_ITEMSEPL, 'text',     ' , ');
193                 $this->createOption('tagItemFooter',     _NPTAGEX_TPL_ITEMFOOT, 'textarea', '');
194                 $this->createOption('tagIndexSeparator', _NPTAGEX_TPL_IDXSEP,   'text',     ' | ');
195                 $this->createOption('tagsonlycurrent',   _NPTAGEX_ONLY_CURRENT, 'yesno',    'no');
196                 $this->createOption('colorfulhighlight', _NPTAGEX_HILIGHT_MODE, 'yesno',    'no');
197                 $this->createOption('highlight',         _NPTAGEX_HILIGHT_NORM, 'text',     '<span class="highlight">\0</span>');
198                 $this->createOption('maxTagLevel',       _NPTAGEX_MAX_TAGLEBEL, 'text',     '6', 'datatype=numerical');
199                 $this->createOption('minTagLevel',       _NPTAGEX_MIN_TAGLEBEL, 'text',     '1', 'datatype=numerical');
200                 $table_q = 'CREATE TABLE IF NOT EXISTS ' . _TAGEX_TABLE . ' ('
201                                  . ' `inum`    INT(9)        NOT NULL default "0" PRIMARY KEY, '
202                                  . ' `itags`   TEXT          NOT NULL, '
203                                  . ' `itagreg` TIMESTAMP(14) NOT NULL'
204                                  . ' )';
205                 sql_query($table_q);
206                 $table_q = 'CREATE TABLE IF NOT EXISTS ' . _TAGEX_KLIST_TABLE . ' ('
207                                  . ' `listid`      INT(9)        NOT NULL AUTO_INCREMENT PRIMARY KEY, '
208                                  . ' `tag`         VARCHAR(255)           default NULL, '
209                                  . ' `inums`       TEXT          NOT NULL, '
210                                  . ' `inums_count` INT(11)       NOT NULL default "0", '
211                                  . ' `ireg`        TIMESTAMP(14) NOT NULL'
212                                  . ' )';
213                 sql_query($table_q);
214         }
215
216         // }}}
217         // {{{ defineMultilanguage()
218
219         /**
220          * Multi language support
221          */
222         function defineMultilanguage()
223         {
224                 $multilang = array(
225                         '_NPTAGEX_ERASE_FLG'    => array(
226                                 'Erase data when uninstall ?',
227                                 'アンインストール時にデータを消去しますか?',
228                         ),
229                         '_NPTAGEX_EDT_TAGORDER' => array(
230                                 'editform tag order',
231                                 'アイテム追加/編集時のタグの並び順',
232                         ),
233                         '_NPTAGEX_ORDER_VALUE'  => array(
234                                 "amount(desc)|1|amount(asc)|2|tag's order|3|random|4",
235                                 'アイテムの多い順|1|アイテムの少ない順|2|タグ順(キャラクターコード順)|3|ランダム|4',
236                         ),
237                         '_NPTAGEX_TPL_AND'      => array(
238                                 "template for 'and'",
239                                 "'and' リンクのテンプレート',
240                         ),
241                         '_NPTAGEX_TPL_OR'       => array(
242                                 "template for 'or'",
243                                 "'or' リンクのテンプレート',
244                         ),
245                         '_NPTAGEX_TPL_TAGIDX'   => array(
246                                 "template for 'tagIndex'",
247                                 'タグのリンクのテンプレート'
248                         ),
249                         '_NPTAGEX_TPL_ITEMHEAD' => array(
250                                 "template for 'tagItemHeader'",
251                                 'タグを含むアイテムごとのヘッダ',
252                         ), 
253                         '_NPTAGEX_TPL_TAGITEMS' => array(
254                                 "template for 'tagItem'",
255                                 'タグを含むアイテム',
256                         ), 
257                         '_NPTAGEX_TPL_ITEMSEPL' => array(
258                                 "template for 'tagItemSeparator'",
259                                 'タグを含むアイテムのセパレータ',
260                         ), 
261                         '_NPTAGEX_TPL_ITEMFOOT' => array(
262                                 "template for 'tagItemFooter'",
263                                 'タグを含むアイテムごとのフッタ',
264                         ), 
265                         '_NPTAGEX_TPL_IDXSEP'   => array(
266                                 "template for 'tagIndexSeparator'",
267                                 'タグのリンクのセパレータ'
268                         ),
269                         '_NPTAGEX_ONLY_CURRENT' => array(
270                                 'show tags only current blog have',
271                                 '表示中のブログのアイテムに登録してあるタグのみ表示'
272                         ), 
273                         '_NPTAGEX_HILIGHT_MODE' => array(
274                                 'colorful highlight mode ?',
275                                 'カラフルハイライトモードにしますか?'
276                         ), 
277                         '_NPTAGEX_HILIGHT_NORM' => array(
278                                 'template for normal highlightmode',
279                                 'ノーマルハイライトモードの時のテンプレート'
280                         ), 
281                         '_NPTAGEX_MAX_TAGLEBEL' => array(
282                                 'MAX tag lebel',
283                                 'タグレベルの最大値'
284                         ), 
285                         '_NPTAGEX_MIN_TAGLEBEL' => array(
286                                 'MAX tag lebel',
287                                 'タグレベルの最小値'
288                         ), 
289                 );
290                 switch (ereg_replace('[\\|/]', '', getLanguageName())) {
291                         case 'japanese-euc':
292                                 foreach ($multilang as $key => $value) {
293                                         define($key, mb_convert_encoding($value[1], 'EUC-JP', 'UTF-8'));
294                                 }
295                                 break;
296                         case 'japanese-utf8':
297                                 foreach ($multilang as $key => $value) {
298                                         define($key, $value[1]);
299                                 }
300                                 break;
301                         default:
302                                 foreach ($multilang as $key => $value) {
303                                         define($key, $value[0]);
304                                 }
305                 }
306         }
307
308         // }}}
309         // {{{ init()
310
311         /**
312          * initialize plugin
313          */
314         function init()
315         {
316                 global $CONF;
317                 $this->defineMultilanguage;
318                 $usePathInfo = ($CONF['URLMode'] == 'pathinfo');
319                 $this->maURL = (($this->plugCheck('MagicalURL2') || $this->plugCheck('Magical')) && $usePathInfo);
320                 $this->cuURL = ($this->plugCheck('CustomURL') && $usePathInfo);
321         }
322
323         // }}}
324         // {{{ uninstall()
325
326         /**
327          * Plugin uninstall and clear plugin's all data if you want.
328          */
329         function uninstall()
330         {
331                 if ($this->getOption('flg_erase') == 'yes') {
332                         sql_query('DROP TABLE IF EXISTS ' . _TAGEX_TABLE);
333                         sql_query('DROP TABLE IF EXISTS ' . _TAGEX_KLIST_TABLE);
334                 }
335         }
336
337         // }}}
338         // {{{ getTableList()
339
340         /**
341          * Plugin has there.
342          */
343         function getTableList()
344         {
345                 return array(
346                         _TAGEX_TABLE,
347                         _TAGEX_KLIST_TABLE
348                 );
349         }
350
351         // }}}
352         // {{{ getEventList()
353
354         /**
355          * Plugin fook these API.
356          * @return array
357          */
358         function getEventList()
359         {
360                 return array(
361                         'PostAddItem',
362                         'AddItemFormExtras',
363                         'PreUpdateItem',
364                         'EditItemFormExtras',
365                         'PreItem',
366                         'PreDeleteItem',
367                         'TemplateExtraFields',
368                 );
369         }
370
371         // }}}
372
373 /**
374  * Private functions
375  */
376
377         // {{{ plugCheck()
378
379         /**
380          * other plugins installed ?
381          * @param string Plugin name
382          * @return bool
383          */
384         private function plugCheck($name)
385         {
386                 global $manager;
387                 return $manager->pluginInstalled('NP_' . $name);
388         }
389
390         // }}}
391         // {{{ quote_smart()
392
393         /**
394          * Quote string befor SQL.
395          * @param mix string, int, or array
396          * @return mix string or int
397          */
398         private function quote_smart($value)
399         {
400 // Escape SQL query strings
401                 if (is_array($value)) {
402                         if (get_magic_quotes_gpc()) {
403                                 $value = array_map("stripslashes", $value);
404                         }
405                         if (!array_map("is_numeric",$value)) {
406                                 if (version_compare(phpversion(),"4.3.0") == "-1") {
407                                         $value = array_map("mysql_escape_string", $value);
408                                 } else {
409                                         $value = array_map("mysql_real_escape_string", $value);
410                                 }
411                         } else {
412                                 $value = intval($value);
413                         }
414                 } else {
415                         if (get_magic_quotes_gpc()) {
416                                 $value = stripslashes($value);
417                         }
418                         if (!is_numeric($value)) {
419                                 if (version_compare(phpversion(), "4.3.0") == "-1") {
420                                         $value = "'" . mysql_escape_string($value) . "'";
421                                 } else {
422                                         $value = "'" . mysql_real_escape_string($value) . "'";
423                                 }
424                         } else {
425                                 $value     = intval($value);
426                         }
427                 }
428                 return $value;
429         }
430
431         // }}}
432
433 /**
434  * Processing of the event fook held from here
435  */
436
437         // {{{ event_PreItem()
438
439         /**
440          * Quote string befor SQL.
441          * @param mix string, int, or array
442          * @return mix string or int
443          */
444         function event_PreItem($data)
445         {
446 // Hightlight tags
447                 global $currentTemplateName;
448                 $currTemplateName    = $this->quote_smart($currentTemplateName);
449                 $templateDescTable   = sql_table('template_desc');
450                 $q_query             = 'SELECT tddesc as result '
451                                                          . 'FROM %s '
452                                                          . 'WHERE tdname = %s';
453                 $q_query             = sprintf($q_query, $templateDescTable, $currTemplateName);
454                 $currentTemplateDesc = quickQuery($q_query);
455                 if (eregi('<highlightTagsAll>', $currentTemplateDesc)) {
456                         $tags = $this->scanExistTags(0, 99999999);
457                         if (empty($tags)) {
458                                 return false;
459                         } else {
460                                 $highlightKeys = array_keys($tags);
461                         }
462                 } elseif (eregi('<highlightTags>', $currentTemplateDesc)) {
463                         $requestT = $this->getNoDecodeQuery('tag');
464                         if (empty($requestT)) {
465                                 return false;
466                         }
467                         $requestTarray = $this->splitRequestTags($requestT);
468                         $reqAND        = array_map(array(&$this, "_rawdecode"), $requestTarray['and']);
469                         if ($requestTarray['or']) {
470                                 $reqOR     = array_map(array(&$this, "_rawdecode"), $requestTarray['or']);
471                         }
472                         if (isset($reqOR)) {
473                                 $highlightKeys = array_merge($reqAND, $reqOR);
474                         } else {
475                                 $highlightKeys = $reqAND;
476                         }
477                 } else {
478                         return false;
479                 }
480                 $template['highlight'] =  $this->getOption('highlight');
481                 $curItem               =& $data['item'];
482                 if ($this->getOption('colorfulhighlight') == 'no') {// original mode
483                         $curItem->body  = highlight($curItem->body, $highlightKeys, $template['highlight']);
484                         $curItem->more  = highlight($curItem->more, $highlightKeys, $template['highlight']);
485                 } else {
486 /**
487  *
488  * use other color for each tags
489  * mod by shizuki
490  *
491  */
492                         $sh = 0;
493                         foreach ($highlightKeys as $qValue) {
494                                 $pattern       = '<span class=\'highlight_' . $sh . '\'>\0</span>';
495                                 $curItem->body = highlight($curItem->body, $qValue, $pattern);
496                                 $sh++;
497                                 if ($sh == 10) {
498                                         $sh = 0;
499                                 }
500                         }
501                         if ($curItem->more) {
502                                 $sh = 0;
503                                 foreach ($highlightKeys as $qValue) {
504                                         $pattern       = '<span class=\'highlight_' . $sh . '\'>\0</span>';
505                                         $curItem->more = highlight($curItem->more, $qValue, $pattern);
506                                         $sh++;
507                                         if ($sh == 10) {
508                                                 $sh = 0;
509                                         }
510                                 }
511                         }
512                 }
513         }
514
515         function event_TemplateExtraFields($data)
516         {
517                 $data['fields']['NP_TagEX'] = array(
518                         'nptagex_and'               => _NPTAGEX_TPL_AND,
519                         'nptagex_or'                => _NPTAGEX_TPL_OR,
520                         'nptagex_tagIndex'          => _NPTAGEX_TPL_TAGIDX,
521                         'nptagex_tagItemHeader'     => _NPTAGEX_TPL_ITEMHEAD,
522                         'nptagex_tagItem'           => _NPTAGEX_TPL_TAGITEMS,
523                         'nptagex_tagItemSeparator'  => _NPTAGEX_TPL_ITEMSEPL,
524                         'nptagex_tagItemFooter'     => _NPTAGEX_TPL_ITEMFOOT,
525                         'nptagex_tagIndexSeparator' => _NPTAGEX_TPL_IDXSEP,
526                         'nptagex_highlight'         => _NPTAGEX_HILIGHT_NORM,
527                 ); 
528         }
529 /**
530  *
531  * extra forms function
532  * mod by shizuki
533  *
534  */
535 /**
536  *
537  * TAG list
538  * Add or Edit Item
539  * TAGs only current blog
540  * written by shizuki
541  * From http://blog.uribou.net/
542  *
543  */
544         function _ItemFormExtras($tagrows, $tagcols, $blogid = 0, $oldforj = '', $itags = '')
545         {
546                 $blogid = intval($blogid);
547 // Exstra form for add or update Item
548                 if (strstr(serverVar('HTTP_USER_AGENT'), 'Gecko')) {
549                         $divStyles = 'height: 24em;'
550                                            . 'width: 95%;'
551                                            . 'overflow: auto;'
552                                            . 'clear: both;'
553                                            . 'border:1px solid lightblue;'
554                                            . 'margin-top:3.8em;'
555                                            . 'padding-left:0.5em;'
556                                            . '-moz-column-count: 3;'
557                                            . '-moz-column-width: 200px;'
558                                            . '-moz-column-gap: 0.5em;';
559                         $txAStyles = ''//'width:10em;'
560                                            . 'width: 95%;'
561                                            . 'height: 200px;';
562                 } else {
563                         $divStyles = 'height: 200px;'
564                                            . 'clear: both;'
565                                            . 'overflow: auto;';
566                         $txAStyles = 'width:95%;';
567                 }
568                 $printData = "\t\t"
569                                    . "<h3>TagEX</h3>\n\t\t"
570 //                                 . '<p style="float:left;width:95%;">' . "\n\t\t\t"
571                                    . '<label for="tagex">Tag(s):</label>' . "\n\t\t\t"
572                                    . '<a href="javascript:resetOlder'
573                                    . "('" . $oldforj . "')"
574                                    . '">[Reset]</a><br />' . "\n\t\t\t"
575                                    . '<textarea id="tagex" name="itags" rows="' . intval($tagrows)
576                                    . '" cols="' . intval($tagcols) . '" style="' . $txAStyles . '"'
577                                    . ' class="tagex">'
578                                    . htmlspecialchars($itags) . '</textarea>' . "\n\t\t"
579 //                                 . '</p>'
580                                    . '<script language="JavaScript" type="text/javascript">' . "\n"
581                                    . '<!--' . "\n"
582                                    . 'function insertag(tag){' . "\n\t"
583                                    . "if(document.getElementById('tagex').value != '')\n\t\t"
584                                    . 'tag = "\n" + tag;' . "\n\t"
585                                    . "document.getElementById('tagex').value += tag;\n"
586                                    . "}\n"
587                                    . "function resetOlder(old){\n\t"
588                                    . "document.getElementById('tagex').value = old;\n"
589                                    . "}\n//-->\n"
590                                    . "</script>\n"
591                                    . '<div style="' . $divStyles . '" class="tagex"><ul>' . "\n";
592                 echo $printData;
593                 $tagOrder = intval($this->getOption('editTagOrder'));
594                 if ($this->getOption('tagsonlycurrent') == no) {
595                         $existTags = $this->scanExistTags(0, 99999999, $tagOrder);
596                 } else {
597                         $existTags = $this->scanExistTags(1, 99999999, $tagOrder, $blogid);
598                 }
599                 if ($existTags) {
600                         $existTags = array_keys($existTags);
601                 }
602                 for ($i=0; $i < count($existTags); $i++) {
603                         $exTags    = htmlspecialchars($existTags[$i]);
604                         $printData = '<li><a href="javascript:insertag'
605                                            . "('" . $exTags . "')" . '">'
606                                            . $exTags . '</a></li>' . "\n";
607                         echo $printData;
608                 }
609                 echo '</ul></div><br style="clear:all;" />' . "\n";
610         }
611
612         function event_AddItemFormExtras($data)
613         {
614 /*              global $CONF, $blogid;
615                 if (is_numeric($blogid)) {
616                         $blogid = intval($blogid);
617                 } else {
618                         $blogid = intval(getBlogIDFromName($blogid));
619                 }
620                 if (empty($blogid)) {
621                         $blogid = intval($CONF['DefaultBlog']);
622                 }*/
623                 $blogid  = intval($data['blog']->blogid);
624 // Call exstra form
625 //              $oldforj    = $itags = '';
626                 $this->_ItemFormExtras(3, 40, $blogid);//, $oldforj, $itags);// <current blog only />
627         }
628
629         function event_EditItemFormExtras($data)
630         {
631 // Initialize tags when it have
632                 $item_id = intval($data['variables']['itemid']);
633                 $query   = 'SELECT itags FROM %s WHERE inum = %d';
634                 $result  = sql_query(sprintf($query, _TAGEX_TABLE, $item_id));
635                 if (mysql_num_rows($result) > 0) {
636                         $itags  = mysql_result($result,0,0);
637                 }
638                 $oldforj = str_replace("\n", '\n', htmlspecialchars($itags));
639 //              $blogid  = getBlogIDFromItemID($item_id);
640                 $blogid  = intval($data['blog']->blogid);//$blogid);
641 // Call exstra form
642 // current blog onry mode
643                 $this->_ItemFormExtras(5, 20, $blogid, $oldforj, $itags);
644         }
645
646         function event_PostAddItem($data)
647         {
648 // Add tags when it add for Item
649                 $itags  = trim(requestVar('itags'));
650                 if (!$itags) {
651                         return;
652                 }
653                 $inum   = intval($data['itemid']);
654                 $query  = 'INSERT INTO %s (inum, itags) VALUES (%d, %s)';
655                 $query  = sprintf($query, _TAGEX_TABLE, $inum, $this->quote_smart($itags));
656                 sql_query($query);
657                 $temp_tags_array = preg_split("/[\r\n,]+/", $itags);
658                 for ($i=0; $i < count($temp_tags_array); $i++) {
659                         $this->mergeTags(trim($temp_tags_array[$i]), $inum);
660                 }
661         } 
662
663         function event_PreUpdateItem($data)
664         {
665 // Add tags when it add for Item
666                 $itags   = trim(requestVar('itags'));
667                 $inum    = intval($data['itemid']);
668                 $query   = 'SELECT itags as result FROM %s WHERE inum = %d';
669                 $oldTags = quickQuery(sprintf($query, _TAGEX_TABLE, $inum));
670                 if ($itags == $oldTags) {
671                         return false;
672                 }
673                 $query = 'DELETE FROM %s WHERE inum = %d';
674                 sql_query(sprintf($query, _TAGEX_TABLE, $inum));
675                 if (!empty($itags)) {
676                         $query  = 'INSERT INTO %s (inum, itags) VALUES (%d, %s)';
677                         $query  = sprintf($query, _TAGEX_TABLE, $inum, $this->quote_smart($itags));
678                         sql_query($query);
679                 }
680                 $old_tags_array = $this->getTags($oldTags);
681                 if (!is_array($old_tags_array)) $old_tags_array = array($old_tags_array);
682                 $new_tags_array = $this->getTags($itags);
683                 $deleteTags     = $this->array_minus_array($old_tags_array, $new_tags_array);
684                 for ($i=0; $i < count($deleteTags); $i++) {
685                         $this->deleteTags($deleteTags[$i], $inum);
686                 }
687                 $addTags = $this->array_minus_array($new_tags_array, $old_tags_array);
688                 for ($i=0; $i < count($addTags); $i++) {
689                         $this->mergeTags($addTags[$i], $inum);
690                 }
691                 
692         }
693
694         function event_PreDeleteItem($data)
695         {
696 // Delete tags when it for deleted Item
697 // or delete Itemid from TAG table
698                 $inum    = intval($data['itemid']);
699                 $query   = 'SELECT itags as result FROM %s WHERE inum = %d';
700                 $oldTags = quickQuery(sprintf($query, _TAGEX_TABLE, $inum));
701                 if (empty($oldTags)) {
702                         return false;
703                 } else {
704                         $query      = 'DELETE FROM %s WHERE inum = %d';
705                         sql_query(sprintf($query, _TAGEX_TABLE, $inum));
706                         $deleteTags = $this->getTags($oldTags);
707                         for ($i=0; $i < count($deleteTags); $i++) {
708                                 $this->deleteTags($deleteTags[$i], $inum);
709                         }
710                 }
711         }
712
713 //------------------------------------------------------
714
715         function getTags($str)
716         {
717 // extract Item's TAG for array
718                 if (!$str) return false;
719                 $tempArray   = preg_split("/[\r\n,]+/", $str);
720                 $returnArray = array_map('trim', $tempArray);
721                 return array_unique($returnArray);
722         }
723
724         function array_minus_array($a, $b)
725         {
726 // update Item's TAGs
727                 $c = array_diff($a,$b);
728                 $c = array_intersect($c, $a);
729                 return array_values($c); 
730         }
731
732         function deleteTags($tag, $inum)
733         {
734 // Delete TAGs and TAG's Item
735                 $inum    = intval($inum);
736                 $tag     = $this->quote_smart($tag);
737                 $f_query = "SELECT inums FROM " . _TAGEX_KLIST_TABLE
738                                  . " WHERE tag = " . $tag
739                                  . '       AND inums REGEXP "(^|,)' . $inum . '(,|$)"'
740                                  . ' ORDER BY ireg DESC';
741                 $findres = sql_query($f_query);
742                 if (mysql_num_rows($findres) == 0) {
743                         return;
744                 }
745                 $temp_inums = mysql_result($findres, 0, 0);
746                 if (preg_match('/^\d+$/', $temp_inums) && $inum == $temp_inums) {
747                         $query = 'DELETE FROM %s WHERE tag = %s';
748                         sql_query(sprintf($query, _TAGEX_KLIST_TABLE, $tag));
749                         return;
750                 }
751                 $inums_array = array();
752                 $inums_array = explode(',', $temp_inums);
753                 $trans       = array_flip($inums_array);
754                 unset($trans[$inum]);
755                 $inums_array = array_flip($trans);
756                 $inums_count = count($inums_array);
757 //              $inums       = @implode(",", $inums_array);
758                 $inums       = implode(",", $inums_array);
759                 if (!empty($inums)) {
760                         $update_query = 'UPDATE %s '
761                                                   . 'SET inums   = %s, '
762                                                   . 'inums_count = %d '
763                                                   . 'WHERE tag   = %s';
764                         $iCount       = intval($inums_count);
765                         $quoteInums   = $this->quote_smart($inums);
766                         sql_query(sprintf($update_query, _TAGEX_KLIST_TABLE, $quoteInums, $iCount, $tag));
767                 }
768         }
769
770         function mergeTags($tag, $inum)
771         {
772 // Add TAG's Item
773                 if (empty($tag)) {
774                         return;
775                 }
776
777                 $inums_array = array();
778
779                 $inum    = intval($inum);
780                 $tag     = $this->quote_smart($tag);
781                 $f_query = 'SELECT inums'
782                                  . ' FROM ' . _TAGEX_KLIST_TABLE
783                                  . ' WHERE tag = ' . $tag
784                                  . ' ORDER BY ireg DESC';
785                 $findres = sql_query($f_query);
786                 if (mysql_num_rows($findres) > 0) {
787                         $temp_inums  = mysql_result($findres, 0, 0);
788                         $inums_array = explode(',', $temp_inums);
789                         if (!in_array($inum, $inums_array)) {
790                                 $inums       = $temp_inums . ',' . $inum;
791                                 $inums_count = count($inums_array) + 1;
792                         }
793                 } else {
794                         $q_query = 'INSERT INTO %s '
795                                          . '(tag, inums, inums_count) '
796                                          . 'VALUES (%s, %d, 1)';
797                         sql_query(sprintf($q_query, _TAGEX_KLIST_TABLE, $tag, intval($inum)));
798                 }
799                 
800                 if (!empty($inums)) {
801                         $q_query    = 'UPDATE %s SET inums = %s, inums_count = %d WHERE tag = %s';
802                         $iCount     = intval($inums_count);
803                         $quoteInums = $this->quote_smart($inums);
804                         sql_query(sprintf($q_query, _TAGEX_KLIST_TABLE, $quoteInums, $iCount, $tag));
805                 }
806         }
807
808         function scanExistItem($narrowMode = 0, $blogid = 0)
809         {
810 /// Select Items when Categories or Sub-categories or Archive selected
811                 global $manager, $CONF, $blog, $catid, $archive;
812                 if (!$narrowMode) {
813                         return;
814                 }
815                 if ($blogid > 0) {
816                         $b =& $manager->getBlog($blogid);
817                 } elseif ($blog) {
818                         $b =& $blog; 
819                 } else {
820                         $b =& $manager->getBlog($CONF['DefaultBlog']);
821                 }
822                 $where = '';
823                 if ($narrowMode > 0) {
824                                 $where .= ' and i.iblog = ' . intval($b->getID());
825                 }
826                 if ($catid && $narrowMode > 1) {
827                         $catid = intval($catid);
828                         if ($manager->pluginInstalled('NP_MultipleCategories')) {
829                                 $where .= ' and ((i.inumber = p.item_id'
830                                                 . ' and (p.categories REGEXP "(^|,)' . $catid . '(,|$)"'
831                                                 . ' or  i.icat = ' . $catid . '))'
832                                                 . ' or (i.icat = ' . $catid
833                                                 . ' and p.item_id IS NULL))';
834                                 $mtable = ' LEFT JOIN '
835                                                 . sql_table('plug_multiple_categories') . ' as p'
836                                                 . ' ON  i.inumber = p.item_id';
837                                 $mplugin =& $manager->getPlugin('NP_MultipleCategories');
838                                 global $subcatid;
839                                 if ($subcatid && method_exists($mplugin, 'getRequestName')) {
840 //family
841                                         $subcatid   = intval($subcatid);
842                                         $scatTable  = sql_table('plug_multiple_categories_sub');
843                                         $tres_query = 'SELECT * FROM %s WHERE scatid = %d';
844                                         $tres_query = sprintf($tres_query, $scatTable, $subcatid);
845                                         $tres       = sql_query($tres_query);
846                                         $ra         = mysql_fetch_array($tres, MYSQL_ASSOC);
847                                         if (array_key_exists('parentid', $ra)) {
848                                                 $Children = array();
849                                                 $Children = explode('/', $subcatid . $this->getChildren($subcatid));
850                                         }
851                                         if ($loop = count($Children) >= 2) {
852                                                 for ($i=0; $i < $loop; $i++) {
853                                                         $chidID     = intval($Children[$i]);
854                                                         $temp_whr[] = ' p.subcategories REGEXP "(^|,)' . $chidID . '(,|$)" ';
855                                                 }
856                                                 $where .= ' and ( '
857                                                                 . implode (' or ', $temp_whr)
858                                                                 . ' )';
859                                         } else {
860                                                 $where .= ' and p.subcategories REGEXP "(^|,)' . $subcatid . '(,|$)"';
861                                         }
862 //family end
863                                 }
864                         } else {
865                                 $where .= ' and i.icat = ' . $catid;
866                         }
867                 }
868
869                 if ($archive) {
870                         $y = $m = $d = '';
871                         sscanf($archive, '%d-%d-%d', $y, $m, $d);
872                         if ($d) {
873                                 $timestamp_start = mktime(0, 0, 0, $m,   $d,   $y);
874                                 $timestamp_end   = mktime(0, 0, 0, $m,   $d+1, $y);  
875                         } elseif ($m) {
876                                 $timestamp_start = mktime(0, 0, 0, $m,   1,    $y);
877                                 $timestamp_end   = mktime(0, 0, 0, $m+1, 1,    $y);
878                         } else {
879                                 $timestamp_start = mktime(0, 0, 0, 1,    1,    $y);
880                                 $timestamp_end   = mktime(0, 0, 0, 1,    1,    $y+1);
881                         }
882                         $where .= ' and i.itime >= ' . mysqldate($timestamp_start)
883                                 . ' and i.itime < '  . mysqldate($timestamp_end);
884                 } else {
885                         $where .= ' and i.itime <= ' . mysqldate($b->getCorrectTime());
886                 }
887
888                 $iquery = 'SELECT i.inumber '
889                                 . 'FROM %s as i'
890                                 . $mtable
891                                 . ' WHERE i.idraft = 0'
892                                 . $where;
893                 $res    = sql_query(sprintf($iquery, sql_table('item')));
894                 while ($row = mysql_fetch_row($res)) {
895                         $existInums[] = $row[0];
896                 }
897                 return $existInums;
898         }
899
900 /**
901  *
902  * TAG list sort
903  * add TAG's order and Random sort
904  * written by shizuki
905  * From http://blog.uribou.net/
906  *
907  */
908         function sortTags($tags, $sortMode = 0)
909         {
910                 // sortMode 0:none
911                 // sortMode 1:max first
912                 // sortMode 2:min first
913                 // sortMode 3:tag's order
914                 // sortMode 4:random
915                 $sortMode = intval($sortMode);
916                 if (!$tags || $sortMode == 0) {
917                         return $tags;
918                 }
919                 foreach ($tags as $tag => $inums) {
920                         $tagCount[$tag] = count($inums);
921                 }
922                 switch ($sortMode) {
923                         case 1:
924                                 arsort($tagCount);
925                                 break;
926                         case 2:
927                                 asort($tagCount);
928                                 break;
929                         case 3:
930                                 uksort($tagCount, array(&$this, 'sortTagOrder'));
931                                 break;
932                         case 4:
933                                 srand ((float) microtime() * 10000000);
934                                 $tmp_key  = array_rand($tagCount, count($tagCount));
935                                 unset($tagCount);
936                                 $tagCount = array();
937                                 foreach ($tmp_key as $k => $v) {
938                                         $tagCount[$v] = 0;
939                                 }
940                                 break;
941                         default:
942                                 break;
943                 }
944                 foreach ($tagCount as $k => $v) {
945                         $r[$k] = $tags[$k];
946                 }
947                 return $r;
948         }
949
950         function sortTagOrder($a, $b)
951         {
952                 return strcasecmp($a, $b);
953         }
954
955         function scanExistTags($narrowMode = 0, $amount = 99999999, $sortmode = 0, $blogid = 0)
956         {
957 // Select TAG's Item
958                 // $narrowMode = 0: all blogs
959                 // $narrowMode = 1: currentblog only
960                 // $narrowMode = 2: narrowed with catid/subcatid
961                 $narrowMode = intval($narrowMode);
962                 $amount     = intval($amount);
963                 $sortmode   = intval($sortmode);
964 // <mod by shizuki />
965                 if (is_numeric($blogid)) {
966                         $blogid = intval($blogid);
967                 } else {
968                         $blogid = intval(getBlogIDFromName($blogid));
969                 }
970                 $existInums = array();
971                 $existInums = $this->scanExistItem($narrowMode, $blogid);
972                 $res        = sql_query(sprintf('SELECT * FROM %s', _TAGEX_KLIST_TABLE));
973                 while ($o = mysql_fetch_object($res)) {
974                         $tagsk[$o->tag] = explode(',', $o->inums);
975                         if ($existInums) {
976                                 $tagsk[$o->tag] = array_intersect($tagsk[$o->tag], $existInums);
977                                 $tagsk[$o->tag] = array_values($tagsk[$o->tag]);
978                         }
979                         if (empty($tagsk[$o->tag])) {
980                                 unset($tagsk[$o->tag]);
981                         }
982                 }
983                 $tagsk = $this->sortTags($tagsk, $sortmode);
984                 if (count($tagsk) > $amount) {
985                         $tagsk = array_slice($tagsk, 0, $amount);
986                 }
987                 return $tagsk;
988         }
989
990         function scanCount($tags)
991         {
992 // ? count TAGs have Item ?
993                 $max = $min = 1;
994                 foreach ($tags as $tag) {
995                         $tempCount = count($tag);
996                         $max       = max($max, $tempCount);
997                         $min       = min($min, $tempCount);
998                 }
999                 return array($max, $min);
1000         }
1001
1002         function getNoDecodeQuery($q)
1003         {
1004 // Get urlencoded TAGs
1005                 global $CONF, $manager;
1006 // FancyURL
1007                 if ($CONF['URLMode'] == 'pathinfo') {
1008                         $urlq  = serverVar('REQUEST_URI');
1009                         $tempq = explode($q . '/', $urlq, 2);
1010                         if ($this->maURL) {//($manager->pluginInstalled('NP_MagicalURL2') || $manager->pluginInstalled('NP_Magical')) {
1011                                 $tempq = explode($q . '_', $urlq, 2);
1012                         }
1013 //                      if ($tempq[1]) {
1014                         if (!empty($tempq[1])) {
1015                                 $tagq = explode('/', $tempq[1]);
1016                                 if ($this->maURL) {//($manager->pluginInstalled('NP_MagicalURL2') || $manager->pluginInstalled('NP_Magical')) {
1017                                         $tagq = explode('_', $tempq[1]);
1018                                 }
1019                                 $str  = preg_replace('|[^a-z0-9-~+_.#;,:@%]|i', '', $tagq[0]);
1020                                 return $str;
1021                         }
1022                 } else {
1023 // NormalURL
1024                         $urlq = serverVar('QUERY_STRING');
1025                         $urlq = str_replace('?', '', $urlq);
1026                         $urlq = explode('&', $urlq);
1027                         $qCnt = count($urlq);
1028                         for ($i=0; $i<$qCnt; $i++) {
1029                                 $tempq = explode('=', $urlq[$i]);
1030                                 if ($tempq[0] == $q) {
1031                                         $str = preg_replace('|[^a-z0-9-~+_.#;,:@%]|i', '', $tempq[1]);
1032                                         return $str;
1033                                 }
1034                         }
1035                 }
1036                 return FALSE;
1037         }
1038
1039         function splitRequestTags($q)
1040         {
1041 // extract TAGs to array
1042                 if (!strpos($q, '+') && !strpos($q, ':')) {
1043                         $res['and'][0] = $q;
1044                         return $res;
1045                 }
1046                 $res     = array(
1047                                                  'and' => array(),
1048                                                  'or'  => array(),
1049                                                 );
1050                 $tempAnd = explode('+', $q);
1051                 $andCnt  = count($tempAnd);
1052                 for ($i=0; $i < $andCnt; $i++) {
1053                         $temp         = explode(':', $tempAnd[$i]);
1054                         $res['and'][] = array_shift($temp);
1055                         if ($temp != array()) {
1056                                 $res['or'] = array_merge($res['or'], $temp);
1057                         }
1058                 }
1059                 return $res;
1060         }
1061
1062         function doIf($key, $value)
1063         {
1064                 if ($key != 'tag') {
1065                         return false;
1066                 }
1067                 $reqTags = $this->getNoDecodeQuery('tag');
1068                 if (!empty($reqTags)) {
1069                         $reqTagsArr = $this->splitRequestTags($reqTags);
1070                         $reqAND     = array_map(array(&$this, "_rawdecode"), $reqTagsArr['and']);
1071                         if ($requestTarray['or']) {
1072                                 $reqOR = array_map(array(&$this, "_rawdecode"), $reqTagsArr['or']);
1073                         }
1074                 } else {
1075                         return false;
1076                 }
1077                 if (empty($value)) {
1078                         return true;
1079                 } else {
1080                         $tagsArray = ($reqOR) ? array_merge($reqAND, $reqOR) : $reqAND;
1081                         return in_array($value, $tagsArray);
1082                 }
1083         }
1084
1085         function doSkinVar($skinType, $type='list20/1/0/1/4')
1086         {
1087 //      global $ecatid;
1088 //      echo 'ecat='.$ecatid.'<br />';
1089                 // type[0]: type ( + amount (int))
1090                 // type[1]: $narrowMode (0/1/2)
1091                 // type[2]: sortMode (1/2/3/4)
1092                 // type[3]: Minimum font-sizem(em) 0.5/1/1.5/2...
1093                 // type[4]: Maximum font-sizem(em)
1094                 $maxtaglevel = $this->getOption('maxTagLevel');
1095                 $mintaglevel = $this->getOption('minTagLevel');
1096                 $taglevel    = 1;
1097 // default
1098                 if (empty($type)) {
1099                         $type = 'list20/2/1/1/4';
1100                 }
1101                 $type = explode('/', $type);
1102                 if (eregi('list', $type[0])) {
1103                         $amount  = eregi_replace("list", "", $type[0]);
1104                         $type[0] = 'list';
1105 // keywords="TAG"
1106                 } elseif (eregi('meta', $type[0])) {
1107                         $amount  = eregi_replace("meta", "", $type[0]);
1108                         $type[0] = 'meta';
1109                 }
1110 // default amount
1111                 $amount = (!empty($amount)) ?  intval($amount):  99999999;
1112
1113                 $defaultType = array('list', '1', '0', '1', '4');
1114                 $type        = $type + $defaultType;
1115                 $requestT = $this->getNoDecodeQuery('tag');
1116                 if (!empty($requestT)) {
1117                         $requestTarray = $this->splitRequestTags($requestT);
1118                         $reqAND        = array_map(array(&$this, "_rawdecode"), $requestTarray['and']);
1119                         if ($requestTarray['or']) {
1120                                 $reqOR = array_map(array(&$this, "_rawdecode"), $requestTarray['or']);
1121                         }
1122                 }
1123                 switch($type[0]){ 
1124
1125                         case 'tag':
1126                                 if ($requestTarray) {
1127                                         $reqAndLink = array();
1128                                         foreach ($reqAND as $val) {
1129                                                 $reqAndLink[] = '<a href="'
1130                                                                           . $this->creatTagLink($val)
1131                                                                           . '" title="' . $val . '">'
1132                                                                           . $val . '</a>';
1133                                         }
1134                                         $reqANDp = implode('" + "', $reqAndLink);
1135                                         if ($reqOR) {
1136                                                 $reqOrLink = array();
1137                                                 foreach ($reqOR as $val) {
1138                                                         $reqOrLink[] = '<a href="'
1139                                                                                  . $this->creatTagLink($val)
1140                                                                                  . '" title="' . $val . '">'
1141                                                                                  . $val . '</a>';
1142                                                 }
1143                                                 $reqORp = '"</u> or <u>"'
1144                                                                 . implode('"</u> or <u>"', $reqOrLink);
1145                                         }
1146                                         echo '<h1> Tag for <u>"' . $reqANDp . $reqORp . '"</u></h1>';
1147                                 }
1148                                 break;
1149
1150 // meta keywords="TAG"
1151 // and AWS keywords
1152                         case 'meta':
1153                                 global $manager, $itemid;
1154                                 $itemid = intval($itemid);
1155                                 if ($type[3] != 'ad') {
1156                                         echo '<meta name="keywords" content="';
1157                                         $sep = ' ';
1158                                 } elseif ($type[3] == 'ad') {
1159                                         $sep = ' ';
1160                                 }
1161                                 if ($skinType == 'item') {
1162                                         $q   = 'SELECT * FROM %s WHERE inum = %d';
1163                                         $res = sql_query(sprintf($q, _TAGEX_TABLE, $itemid));
1164                                         while ($o = mysql_fetch_object($res)) {
1165                                                 $temp_tags_array = preg_split("/[\n,]+/", trim($o->itags));
1166                                                 $temp_tags_count = count($temp_tags_array);
1167                                                 for ($i=0; $i < $temp_tags_count; $i++) {
1168                                                         $tag         = trim($temp_tags_array[$i]);
1169                                                         $taglist[$i] = htmlspecialchars($tag, ENT_QUOTES, _CHARSET);
1170                                                 }
1171                                         }
1172                                         if ($taglist)
1173                                                 echo implode(' ', $taglist);
1174                                 } else {
1175                                         if ($tags = $this->scanExistTags(intval($type[1]), $amount, intval($type[2]))) {
1176                                                 $eachTag = array();
1177                                                 $t       = 0;
1178                                                 foreach ($tags as $tag => $inums) {
1179                                                         $eachTag[$t] = htmlspecialchars($tag, ENT_QUOTES, _CHARSET);
1180                                                         $t++;
1181                                                 }
1182                                                 if ($type[3] != 'ad') {
1183                                                         echo implode($sep, $eachTag);
1184                                                 } elseif ($type[3] == 'ad') {
1185                                                         $tag_str = implode($sep, $eachTag);
1186                                                 }
1187                                         }
1188                                 }
1189                                 if ($type[3] != 'ad') {
1190                                         echo '" />';
1191                                 } elseif ($type[3] == 'ad') {
1192 //                                      $tag_str = mb_convert_encoding($tag_str, 'UTF-8', 'UTF-8');
1193                                         $tag_str = urlencode($tag_str);
1194                                         echo $tag_str;
1195                                 }
1196                                 break;
1197 // TAG list(tag cloud)
1198                         case 'list':
1199                                 $template['and']               = $this->getOption('and');
1200                                 $template['or']                = $this->getOption('or');
1201                                 $template['tagIndex']          = $this->getOption('tagIndex');
1202                                 $template['tagItemHeader']     = $this->getOption('tagItemHeader');
1203                                 $template['tagItem']           = $this->getOption('tagItem');
1204                                 $template['tagItemSeparator']  = $this->getOption('tagItemSeparator');
1205                                 $template['tagItemFooter']     = $this->getOption('tagItemFooter');
1206                                 $template['tagIndexSeparator'] = $this->getOption('tagIndexSeparator');
1207                                 if ($tags = $this->scanExistTags($type[1])) {
1208                                         if ($type[3] != $type[4]) {
1209                                                 $minFontSize               = min((float)$type[3], (float)$type[4]) - 0.5;
1210                                                 $maxFontSize               = max((float)$type[3], (float)$type[4]);
1211                                                 $levelsum                  = ($maxFontSize - $minFontSize) / 0.5;
1212                                                 $taglevelsum               = $maxtaglevel - $mintaglevel;
1213                                                 list($maxCount, $minCount) = $this->scanCount($tags);
1214                                                 $eachCount                 = ceil(($maxCount - $minCount) / $levelsum);
1215                                         }
1216                                         $select = array();
1217                                         if ($reqAND) {
1218                                                 $req = ($reqOR) ? array_merge($reqAND, $reqOR) : $reqAND;
1219                                                 foreach ($req as $tag) {
1220                                                         if (array_key_exists($tag, $tags)) {
1221                                                                 $select   = array_merge($select, $tags[$tag]);
1222                                                                 $selected = array_unique($select);
1223                                                         }
1224                                                 }
1225                                         }
1226                                         foreach ($tags as $tag => $inums) {
1227                                                 if ($selected) {
1228                                                         if (!in_array($tag, $req)) {
1229 // shiborikomi
1230 //                                                      if (!in_array($tag, $req) && !array_diff($tags[$tag], $selected)) {
1231                                                                 $tagCount[$tag] = count($inums);
1232                                                         }
1233                                                 } else {
1234                                                         $tagCount[$tag] = count($inums);
1235                                                 }
1236                                         }
1237                                         if ($tagCount) {
1238                                                 arsort($tagCount);
1239                                                 foreach ($tagCount as $k => $v) {
1240                                                         $r[$k] = $tags[$k];
1241                                                 }
1242                                                 unset($tags);
1243                                                 if (count($r) > $amount) {
1244                                                         $r = array_slice($r, 0, $amount);
1245                                                 }
1246                                                 $tags = array();
1247                                                 if (count($r) == 1) {
1248                                                         $tags = $r;
1249                                                 } else {
1250                                                         $tags = $this->sortTags($r, intval($type[2]));
1251                                                 }
1252                                         } else {
1253                                                 echo 'No Tags';
1254                                                 return;
1255                                         }
1256                                         $eachTag = array();
1257                                         $t       = 0;
1258                                         foreach ($tags as $tag => $inums) {
1259                                                 $tagitems  = array();
1260                                                 $tagAmount = count($inums);
1261                                                 if ($eachCount) {
1262                                                         $fontlevel = ceil($tagAmount / $eachCount) * 0.5 + $minFontSize;
1263                                                 } else {
1264                                                         $fontlevel = 1;
1265                                                 }
1266                                                 if ($maxCount == $minCount) {//2008-05-22 Cacher
1267                                                         $taglevel = 1;
1268                                                 }else{
1269                                                         $taglevel = round(($tagAmount - $minCount) / ($maxCount - $minCount) * $taglevelsum + $mintaglevel);
1270                                                 }
1271 /// Item's name had TAGs 
1272                                                 $iids = array_slice($inums, 0, 4);
1273                                                 sort($iids);
1274                                                 $qQuery  = ' SELECT '
1275                                                                  . '   SUBSTRING(ititle, 1, 12) as short_title'
1276                                                                  . ' FROM '
1277                                                                  .     sql_table('item')
1278                                                                  . ' WHERE '
1279                                                                  . '   inumber in (' . implode(',', $iids) . ') '
1280                                                                  . 'ORDER BY '
1281                                                                  . '   inumber';
1282                                                 $sTitles = sql_query($qQuery);
1283                                                 $i       = 0;
1284                                                 while ($sTitle = mysql_fetch_assoc($sTitles)) {
1285                                                         $shortTitle = mb_convert_encoding($sTitle['short_title'], _CHARSET, _CHARSET);
1286                                                         $shortTitle = htmlspecialchars($shortTitle, ENT_QUOTES, _CHARSET);
1287                                                         $printData['tagItem']
1288                                                                                 = array(
1289                                                                                                 'itemid'    => intval($iids[$i]),
1290                                                                                                 'itemtitle' => $shortTitle . '..',
1291                                                                                            );
1292                                                         $i++;
1293                                                         $tagitems[] = TEMPLATE::fill($template['tagItem'], $printData['tagItem']);
1294                                                 }
1295                                                 $tagitem = implode($template['tagItemSeparator'], $tagitems) . '...etc.';
1296
1297 // Generate URL link to TAGs
1298                                                 $and = $or = '';
1299 /*********************
1300  * comment out this line when nodisplay selected TAGs */
1301 //                                              $req = ($reqOR) ? array_merge($reqAND, $reqOR) : $reqAND;
1302 /*********************/
1303                                                 if ($req && !in_array($tag, $req)) {
1304                                                         $printData['and'] = array(
1305                                                                 'andurl' => $this->creatTagLink($tag, $type[1], $requestT, '+') //AND link
1306                                                                                                          );
1307                                                         $printData['or']  = array(
1308                                                                 'orurl'  => $this->creatTagLink($tag, $type[1], $requestT, ':') //OR link
1309                                                                                                          );
1310                                                         $and = TEMPLATE::fill($template['and'], $printData['and']);     // insert URL to template
1311                                                         $or  = TEMPLATE::fill($template['or'], $printData['or']);
1312                                                 }
1313
1314 // insert data to template
1315                                                 $printData['tagIndex'] = array(
1316                                                         'and'        => $and,
1317                                                         'or'         => $or,
1318                                                         'tag'        => htmlspecialchars($tag, ENT_QUOTES, _CHARSET),
1319                                                         'tagamount'  => $tagAmount,
1320                                                         'fontlevel'  => $fontlevel,
1321                                                         'taglevel'   => $taglevel,
1322                                                         'taglinkurl' => $this->creatTagLink($tag, intval($type[1])),
1323                                                         'tagitems'   => $tagitem
1324                                                                                                           );
1325                                                 $eachTag[$t]  = TEMPLATE::fill($template['tagIndex'], $printData['tagIndex']);
1326
1327 // format outputdata and data output
1328                                                 $eachTag[$t] .= $template['tagItemHeader'];
1329 /*
1330                                                 if (!ereg('<%tagitems%>', $template['tagIndex'])) {//<%
1331                                                         $eachTag[$t] .= $tagitem;
1332                                                 }
1333 */
1334                                                 $eachTag[$t] .= $template['tagItemFooter'];
1335                                                 $t++;
1336                                         }
1337                                         echo implode($template['tagIndexSeparator'] . "\n", $eachTag);
1338                                 }
1339                                 break;
1340
1341 // show selected TAGs for <title></title>
1342                         case 'title':
1343                                 if ($reqAND) {
1344                                         $req  = ($reqOR) ? array_merge($reqAND, $reqOR) : $reqAND;
1345                                         $data = htmlspecialchars(implode('|', $req), ENT_QUOTES, _CHARSET);
1346                                         echo ' : Selected Tag(s) &raquo; &quot;' . $data . '&quot;';
1347                                 }
1348                                 break;
1349                         default:
1350                                 break;
1351                 }
1352 // end of switch(type)
1353         }
1354
1355         function doTemplateVar(&$item, $type = '')
1356         {
1357 // <highlight selected TAGs mod by shizuki>
1358                 $requestT = $this->getNoDecodeQuery('tag');
1359                 if (!empty($requestT)) {
1360                         $requestTarray = $this->splitRequestTags($requestT);
1361                         $reqAND        = array_map(array(&$this, "_rawdecode"), $requestTarray['and']);
1362                         if($requestTarray['or']) {
1363                                 $reqOR = array_map(array(&$this, "_rawdecode"), $requestTarray['or']);
1364                         }
1365                         $words = ($reqOR)? array_merge($reqAND, $reqOR): $reqAND;
1366                 } else {
1367                         $words = array();
1368                 }
1369                 $iid = intval($item->itemid);
1370                 $q   = 'SELECT * FROM %s WHERE inum = %d';
1371                 $res = sql_query(sprintf($q, _TAGEX_TABLE, $iid));
1372                 while ($o = mysql_fetch_object($res)) {
1373                         $temp_tags_array = preg_split("/[\n,]+/", trim($o->itags));
1374                         $temp_tags_count = count($temp_tags_array);
1375                         for ($i=0; $i < $temp_tags_count; $i++) {
1376                                 $tag     = trim($temp_tags_array[$i]);
1377                                 $taglink = $this->creatTagLink($tag, 0);
1378 // highlight selected TAGs
1379                                 $key     = array_search($tag, $words);
1380                                 if ($key >= 10) {
1381                                         $key = $key - 10;
1382                                 }
1383                                 if (in_array($tag, $words)) {
1384                                         $taglist[$i] = '<a href="'
1385                                                                  . $this->creatTagLink($tag, 0)
1386                                                                  . '" class="highlight_0" rel="tag">'
1387                                                                  . htmlspecialchars($tag, ENT_QUOTES, _CHARSET) . '</a>';
1388                                 } else {
1389                                         $taglist[$i] = '<a href="'
1390                                                                  . $this->creatTagLink($tag, 0)
1391                                                                  . '" rel="tag">'
1392                                                                  . htmlspecialchars($tag, ENT_QUOTES, _CHARSET) . '</a>';
1393                                 }
1394                         }
1395                 }
1396                 if ($taglist) {
1397 //                      echo 'Tag: ' . implode(' / ', $taglist);
1398                         echo implode(' / ', $taglist);
1399                 }
1400         }
1401
1402         function _rawencode($str)
1403         {
1404                 
1405                 if (_CHERSET != 'UTF-8') {
1406                         $str = mb_convert_encoding($str, "UTF-8", _CHARSET);
1407                 }
1408                 $str = rawurlencode($str);
1409                 $str = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%]|i', '', $str);
1410                 return $str;
1411         }
1412
1413         function _rawdecode($str)
1414         {
1415                 $str = rawurldecode($str);
1416                 if (_CHERSET != 'UTF-8') {
1417                         $str = mb_convert_encoding($str, _CHARSET, "UTF-8");
1418                 }
1419                 $str = htmlspecialchars($str);
1420                 return $str;
1421         }
1422
1423         function getChildren($subcat_id)
1424         {
1425                 $subcat_id = intval($subcat_id);
1426                 $que       = 'SELECT'
1427                                    . ' scatid,'
1428                                    . ' parentid,'
1429                                    . ' sname '
1430                                    . 'FROM'
1431                                    . ' %s '
1432                                    . 'WHERE'
1433                                    . ' parentid = %d';
1434                 $mcatTable = sql_table('plug_multiple_categories_sub');
1435                 $que       = sprintf($que, $mcatTable, $subcat_id);
1436                 $res       = sql_query($que);
1437                 while ($so =  mysql_fetch_object($res)) {
1438                         $r .= $this->getChildren($so->scatid)
1439                                 . '/'
1440                                 . $so->scatid;
1441                 }
1442                 return $r;
1443         }
1444
1445         function creatTagLink($tag, $narrowMode = 0, $ready = '', $sep = '')
1446         {
1447                 global $manager, $CONF, $blogid, $catid;        //, $subcatid;
1448                 $linkparams = array();
1449                 if (is_numeric($blogid)) {
1450                         $blogid = intval($blogid);
1451                 } else {
1452                         $blogid = intval(getBlogIDFromName($blogid));
1453                 }
1454                 if (!$blogid) {
1455                         $blogid = $CONF['DefaultBlog'];
1456                 }
1457                 $b =& $manager->getBlog($blogid);
1458                 if ($narrowMode == 2) {
1459                         if ($catid) {
1460                                 $linkparams['catid'] = intval($catid);
1461                         }
1462                         if ($manager->pluginInstalled('NP_MultipleCategories')) {
1463                                 $mcategories =& $manager->getPlugin('NP_MultipleCategories');
1464                                 if (method_exists($mcategories, 'getRequestName')) {
1465                                         $subrequest = $mcategories->getRequestName();
1466                                 } else {
1467                                         $subrequest = 'subcatid';
1468                                 }
1469                                 $mcategories->event_PreSkinParse(array());
1470                                 global $subcatid;
1471                                 if ($subcatid) {
1472                                         $linkparams[$subrequest] = intval($subcatid);
1473                                 }
1474                         }
1475                 }
1476
1477                 if (!empty($ready)) {
1478                         $requestTagsArray = $this->splitRequestTags($ready);
1479                         foreach ($requestTagsArray['and'] as $key => $val) {
1480                                 if (!$this->_isValidTag($val)) {
1481                                         $trush = array_splice($requestTagsArray['and'], $key, 1);
1482                                 }
1483                         }
1484                         $reqAnd = implode('+', $requestTagsArray['and']);
1485                         if (!empty($requestTagsArray['or'])) {
1486                                 foreach ($requestTagsArray['or'] as $key => $val) {
1487                                         if (!$this->_isValidTag($val)) {
1488                                                 $trush = array_splice($requestTagsArray['and'], $key, 1);
1489                                         }
1490                                 }
1491                                 $reqOr = ':' . implode(':', $requestTagsArray['or']);
1492                         }
1493                         $ready = $reqAnd . $reqOr;
1494                 }
1495
1496                 if (!$ready) {
1497                         $sep = '';
1498                 }
1499 //      <mod by shizuki>
1500 /*// <Original URL Generate code>
1501 //              if ($CONF['URLMode'] == 'pathinfo')
1502 //                      $link = $CONF['IndexURL'] . '/tag/' . $ready . $sep . $this->_rawencode($tag);
1503 //              else
1504 //                      $link = $CONF['IndexURL'] . '?tag=' . $ready . $sep . $this->_rawencode($tag);
1505                 $link = $b->getURL();
1506                 if (substr($link, -1) != '/') {
1507                         if (substr($link, -4) != '.php') {
1508                                 $link .= '/';
1509                         }
1510                 }
1511                 if ($CONF['URLMode'] == 'pathinfo') {
1512                         $link .=  'tag/' . $ready . $sep . $this->_rawencode($tag);
1513                 } else {
1514                         $link .= '?tag=' . $ready . $sep . $this->_rawencode($tag);
1515                 }
1516 //  </ Original URL Generate code> */
1517
1518 /*// <test code>
1519         $CONF['BlogURL']   = $b->getURL();
1520                 $linkparams['tag'] = $ready . $sep . $this->_rawencode($tag);
1521                 $uri               = createBlogidLink($blogid, $linkparams);
1522                 if (strstr ($uri, '//')) {
1523                         $uri = preg_replace("/([^:])\/\//", "$1/", $uri);
1524                 }
1525                 return $uri;
1526 // </test code>*/
1527
1528 // </mod by shizuki>*/
1529
1530 //      <mod by shizuki>
1531 //              if ($manager->pluginInstalled('NP_CustomURL')) {
1532                         $linkparams['tag'] = $ready . $sep . $this->_rawencode($tag);
1533                         $uri               = createBlogidLink($blogid, $linkparams);
1534                         if (strstr ($uri, '//')) {
1535                                 $uri = preg_replace("/([^:])\/\//", "$1/", $uri);
1536                         }
1537                         return $uri;
1538 /*              } elseif ($manager->pluginInstalled('NP_MagicalURL2') || $manager->pluginInstalled('NP_Magical')) {
1539                         $uri = createBlogidLink($blogid, $linkparams);
1540                         if (strstr ($uri, '//')) {
1541                                 $uri = preg_replace("/([^:])\/\//", "$1/", $uri);
1542                         }
1543                         $uri = substr($uri, 0, -5) . '_tag' . $ready . $sep . $this->_rawencode($tag);
1544                         return $uri;
1545                 }
1546 // </mod by shizuki>*/
1547
1548 //              return addLinkParams($link, $linkparams);
1549         }
1550
1551 /**
1552  * function Tag valid
1553  * add by shizuki
1554  */
1555         function _isValidTag($encodedTag)
1556         {
1557                 $encodedTag = rawurldecode($encodedTag);
1558                 if (_CHERSET != 'UTF-8') {
1559                         $str = mb_convert_encoding($encodedTag, _CHARSET, "UTF-8");
1560                 }
1561                 $str  = $this->quote_smart($str);
1562                 $q    = 'SELECT listid as result FROM %s WHERE tag = %s';
1563                 $Vali = quickQuery(sprintf($q, _TAGEX_KLIST_TABLE, $str));
1564                 if (!empty($Vali)) {
1565                         return TRUE;
1566                 } else {
1567                         return FALSE;
1568                 }
1569         }
1570
1571 }