root/branches/athena/php/lib/mtdb_base.php @ 1092

Revision 1092, 85.3 kB (checked in by hachi, 2 years ago)

Merging release-15 to athena branch. svn merge -r59987:60375 http://svn.sixapart.com/repos/eng/movabletype/branches/release-15 .

  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2# Copyright 2001-2007 Six Apart. This code cannot be redistributed without
3# permission from www.sixapart.com.  For more information, consult your
4# Movable Type license.
5#
6# $Id$
7
8class MTDatabaseBase extends ezsql {
9    var $savedqueries = array();
10    var $_entry_id_cache = array();
11    var $_author_id_cache = array();
12    var $_comment_count_cache = array();
13    var $_ping_count_cache = array();
14    var $_cat_id_cache = array();
15    var $_tag_id_cache = array();
16    var $_blog_id_cache = array();
17    var $_entry_link_cache = array();
18    var $_cat_link_cache = array();
19    var $_archive_link_cache = array();
20    var $_entry_tag_cache = array();
21    var $_blog_tag_cache = array();
22    var $_asset_tag_cache = array();
23    var $_blog_asset_tag_cache = array();
24    var $serializer;
25    var $id;
26
27    function MTDatabaseBase($dbuser, $dbpassword = '', $dbname = '', $dbhost = '', $dbport = '') {
28        $this->id = md5(uniqid('MTDatabaseBase',true));
29        $this->hide_errors();
30        $this->db($dbuser, $dbpassword, $dbname, $dbhost, $dbport);
31    }
32
33    function unserialize($data) {
34        if (!$this->serializer) {
35            require_once("MTSerialize.php");
36            $this->serializer =& new MTSerialize();
37        }
38        return $this->serializer->unserialize($data);
39    }
40
41    function query($query) {
42        $this->savedqueries[] = $query;
43        parent::query($query);
44    }
45
46    function &resolve_url($path, $blog_id) {
47        $path = preg_replace('!/$!', '', $path);
48        $path = $this->escape($path);
49        $blog_id = intval($blog_id);
50        # resolve for $path -- one of:
51        #      /path/to/file.html
52        #      /path/to/index.html
53        #      /path/to/
54        #      /path/to
55        global $mt;
56        $index = $this->escape($mt->config('IndexBasename'));
57        $escindex = $this->escape($index);
58        foreach ( array($path, urldecode($path), urlencode($path)) as $p ) {
59            $sql = "
60                select *
61                  from mt_blog, mt_template, mt_fileinfo
62                  left outer join mt_templatemap on templatemap_id = fileinfo_templatemap_id
63                 where fileinfo_blog_id = $blog_id
64                       and ((fileinfo_url = '%1\$s' or fileinfo_url = '%1\$s/') or (fileinfo_url like '%1\$s/$escindex%%'))
65                   and blog_id = fileinfo_blog_id
66                   and template_id = fileinfo_template_id
67                 order by length(fileinfo_url) asc
68            ";
69            $rows = $this->get_results(sprintf($sql,$p), ARRAY_A);
70            if ($rows) {
71                break;
72            }
73        }
74        $path = $p;
75        if (!$rows) return null;
76
77        $found = false;
78        foreach ($rows as $row) {
79            $fiurl = $row['fileinfo_url'];
80            if ($fiurl == $path) {
81                $found = true;
82                break;
83            }
84            if ($fiurl == "$path/") {
85                $found = true;
86                break;
87            }
88            $ext = $row['blog_file_extension'];
89            if (!empty($ext)) $ext = '.' . $ext;
90            if ($fiurl == ($path.'/'.$index.$ext)) {
91                $found = true; break;
92            }
93            if ($found) break;
94        }
95        if (!$found) return null;
96        $data = array();
97        foreach ($row as $key => $value) {
98            if (preg_match('/^([a-z]+)/', $key, $matches)) {
99                $data[$matches[1]][$key] = $value;
100            }
101        }
102        $this->_blog_id_cache[$data['blog']['blog_id']] =& $data['blog'];
103        return $data;
104    }
105
106    function fetch_blogs($args) {
107
108        if ($blog_ids = $this->include_exclude_blogs($args)) {
109            $where = ' where blog_id ' . $blog_ids;
110        }
111        $sql = 'select * from mt_blog'
112            . $where . ' order by blog_name';
113        $res = $this->get_results($sql, ARRAY_A);
114        return $res;
115    }
116
117    function fetch_templates($args) {
118        if (isset($args['type'])) {
119            $type_filter = 'and template_type = \'' . $this->escape($args['type']) . '\'';
120        }
121        if (isset($args['blog_id'])) {
122            $blog_filter = 'and template_blog_id = ' . intval($args['blog_id']);
123        }
124        $sql = "select *
125                  from mt_template
126                 where 1 = 1
127                       $blog_filter
128                       $type_filter
129              order by template_name";
130        $result = $this->get_results($sql, ARRAY_A);
131        return $result;
132    }
133
134    function load_index_template(&$ctx, $tmpl, $blog_id = null) {
135        return $this->load_special_template($ctx, $tmpl, 'index');
136    }
137
138    function load_special_template(&$ctx, $tmpl, $type, $blog_id = null) {
139        $blog_id or $blog_id = $ctx->stash('blog_id');
140        $tmpl_name = $this->escape($tmpl);
141        $sql = "select * from mt_template" .
142            " where template_blog_id=$blog_id ".
143            ($tmpl ? " and (template_name='".$this->escape($tmpl) . "'" .
144            " or template_outfile='" . $tmpl_name ."')" .
145            " or template_identifier='" . $tmpl_name . "'" : "").
146            " and template_type='".$this->escape($type)."'";
147        list($row) = $this->get_results($sql, ARRAY_A);
148        if (!$row) return null;
149        return $row;
150    }
151
152    function fetch_config() {
153        $sql = "select * from mt_config";
154        list($row) = $this->get_results($sql, ARRAY_A);
155        if (!$row) return null;
156        return $row;
157    }
158
159    function category_link($cid, $args = null) {
160        if (isset($this->_cat_link_cache[$cid])) {
161            $url = $this->_cat_link_cache[$cid];
162        } else {
163            $sql = "select fileinfo_url, fileinfo_blog_id
164                      from mt_fileinfo, mt_templatemap
165                     where fileinfo_category_id = $cid
166                       and fileinfo_archive_type = 'Category'
167                       and templatemap_id = fileinfo_templatemap_id
168                       and templatemap_is_preferred = 1";
169            $rows = $this->get_results($sql, ARRAY_A);
170            if (count($rows)) {
171                $link =& $rows[0];
172            } else {
173                return null;
174            }
175            $blog =& $this->fetch_blog($link['fileinfo_blog_id']);
176            $blog_url = $blog['blog_site_url'];
177            $blog_url = preg_replace('!(https?://(?:[^/]+))/.*!', '$1', $blog_url);
178            $url = $blog_url . $link['fileinfo_url'];
179            $url = _strip_index($url, $blog);
180            $this->_cat_link_cache[$cid] = $url;
181        }
182        return $url;
183    }
184
185    function archive_link($ts, $at, $sql, $args) {
186        $blog_id = intval($args['blog_id']);
187        if (isset($this->_archive_link_cache[$blog_id.';'.$ts.';'.$at])) {
188            $url = $this->_archive_link_cache[$blog_id.';'.$ts.';'.$at];
189        } else {
190            if ($sql == '') {
191                $sql = "select fileinfo_url
192                          from mt_fileinfo, mt_templatemap
193                         where fileinfo_startdate = '$ts'
194                           and fileinfo_blog_id = $blog_id
195                           and fileinfo_archive_type = '".$this->escape($at)."'
196                           and templatemap_id = fileinfo_templatemap_id
197                           and templatemap_is_preferred = 1";
198            }
199            $rows = $this->get_results($sql, ARRAY_A);
200            if (count($rows)) {
201                $link =& $rows[0];
202            } else {
203                return null;
204            }
205            $blog =& $this->fetch_blog($blog_id);
206            $blog_url = $blog['blog_site_url'];
207            $blog_url = preg_replace('!(https?://(?:[^/]+))/.*!', '$1', $blog_url);
208            $url = $blog_url . $link['fileinfo_url'];
209            $url = _strip_index($url, $blog);
210            $this->_archive_link_cache[$ts.';'.$at] = $url;
211        }
212        return $url;
213    }
214
215    function entry_link($eid, $at = "Individual", $args = null) {
216        $blog_id = intval($args['blog_id']);
217        if (isset($this->_entry_link_cache[$eid.';'.$at])) {
218            $url = $this->_entry_link_cache[$eid.';'.$at];
219        } else {
220            if (preg_match('/Category/', $at)) {
221                $table = ", mt_placement";
222                $filter = "and placement_entry_id = $eid
223                           and fileinfo_category_id = placement_category_id
224                           and placement_is_primary = 1";
225            }
226            $entry = $this->fetch_entry($eid);
227            $ts = $entry['entry_authored_on'];
228            if (preg_match('/Monthly$/', $at)) {
229                $ts = substr($ts, 0, 6) . '01000000';
230            } elseif (preg_match('/Daily$/', $at)) {
231                $ts = substr($ts, 0, 8) . '000000';
232            } elseif (preg_match('/Weekly$/', $at)) {
233                require_once("MTUtil.php");
234                list($ws, $we) = start_end_week($ts);
235                $ts = $ws;
236            } elseif (preg_match('/Yearly$/', $at)) {
237                $ts = substr($ts, 0, 4) . '0101000000';
238            } elseif ($at == 'Individual') {
239                $filter .= "and fileinfo_entry_id = $eid";
240            }
241            if ($ts != $entry['entry_authored_on']) {
242                $filter .= " and fileinfo_startdate = '$ts'";
243            }
244            if (preg_match('/Author/', $at)) {
245                $filter .= " and fileinfo_author_id = ". $entry['entry_author_id'];
246            }
247            $sql = "select fileinfo_url, fileinfo_blog_id
248                     from mt_fileinfo, mt_templatemap $table
249                    where templatemap_id = fileinfo_templatemap_id
250                      and fileinfo_blog_id = $blog_id
251                      $filter
252                      and templatemap_archive_type = '$at'
253                      and templatemap_is_preferred = 1";
254            $rows = $this->get_results($sql, ARRAY_A);
255            if (count($rows)) {
256                $link =& $rows[0];
257            } else {
258                return null;
259            }
260            $blog =& $this->fetch_blog($link['fileinfo_blog_id']);
261            $blog_url = $blog['blog_site_url'];
262            $blog_url = preg_replace('!(https?://(?:[^/]+))/.*!', '$1', $blog_url);
263            $url = $blog_url . $link['fileinfo_url'];
264            $url = _strip_index($url, $blog);
265            $this->_entry_link_cache[$eid.';'.$at] = $url;
266        }
267        if ($at != 'Individual' && $at != 'Page') {
268            if (!$args || !isset($args['no_anchor'])) {
269                $url .= '#' . (!$args || isset($args['valid_html']) ? 'a' : '') .
270                        sprintf("%06d", $eid);
271            }
272        }
273        return $url;
274    }
275
276    /* recreation of generic load method functionality from MT::Object */
277    function &load($class, $terms = null, $args = null) {
278        $sql = "select * from mt_$class";
279        $where = '';
280        if ($terms) {
281            if (is_array($terms)) {
282                foreach ($terms as $col => $val) {
283                    $column = $class . '_' . $col;
284                    if (isset($args['range']) && isset($args['range'][$col])) {
285                        $range = '';
286                        if (isset($val[0]))
287                            $range = "$column > '" . $this->escape($val[0]) . "' ";
288                        if (isset($val[1])) {
289                            if ($range != '') $range .= ' and ';
290                            $range .= "$column < '" . $this->escape($val[0]) . "'";
291                        }
292                        $where .= " and ($range)";
293                    } elseif (isset($args['range_incl']) && isset($args['range_incl'][$col])) {
294                        $range = '';
295                        if (isset($val[0]))
296                            $range = "$column >= '" . $this->escape($val[0]) . "' ";
297                        if (isset($val[1])) {
298                            if ($range != '') $range .= ' and ';
299                            $range .= "$column <= '" . $this->escape($val[0]) . "'";
300                        }
301                        $where .= " and ($range)";
302                    } else {
303                        if (is_array($val)) {
304                            $list = '';
305                            foreach ($val as $item) {
306                                if ($list != '') $list .= ',';
307                                $list .= "'" . $this->escape($item). "'";
308                            }
309                            $where .= " and ($column in ($list))";
310                        } else {
311                            $where .= " and ($column='".$this->escape($val)."')";
312                        }
313                    }
314                }
315                $where = preg_replace('/^ and/', '', $where);
316            } else {
317                $where = " ($class"."_id=".intval($terms).")";
318            }
319            $sql .= ' where ' . $where;
320        }
321        if (isset($args['sort']) or isset($args['direction'])) {
322            $order = $args['sort'];
323            $order or $order = 'id';
324            $dir = $args['direction'] == 'descend' ? 'desc' : 'asc';
325            $sql .= " order by " . $class . "_" . $order . " $dir";
326        }
327        if (isset($args['limit']) or isset($args['offset'])) {
328            $sql .= ' <LIMIT>';
329            $sql = $this->apply_limit_sql($sql, $args['limit'], $args['offset']);
330        }
331        return $this->get_results($sql, ARRAY_A);
332    }
333
334    function get_template_text($ctx, $module, $blog_id = null, $type = 'custom') {
335        $blog_id or $blog_id = $ctx->stash('blog_id');
336        if (($type === 'custom' || $type === 'widget')) {
337            $col = 'template_name';
338            $type_filter = "and template_type='$type'";
339        } else {
340            $col = 'template_identifier';
341            $type_filter = "";
342        }
343        $row = $this->get_row("
344            select template_text, template_modified_on, template_linked_file, template_linked_file_mtime, template_linked_file_size
345              from mt_template
346             where template_blog_id=".$this->escape($blog_id)."
347               and $col='".$this->escape($module)."'
348               $type_filter", ARRAY_N);
349        if (!$row) return '';
350        list($tmpl, $ts, $file, $mtime, $size) = $row;
351        if ($file) {
352            if (!file_exists($file)) {
353                $blog = $ctx->stash('blog');
354                if ($blog['blog_id'] != $blog_id) {
355                    $blog = $this->fetch_blog($blog_id);
356                }
357                $path = $blog['blog_site_path'];
358                if (!preg_match('![\\/]$!', $path))
359                    $path .= '/';
360                $path .= $file;
361                if (is_file($path) && is_readable($path))
362                    $file = $path;
363                else
364                    $file = '';
365            }
366            if ($file) {
367                if ((filemtime($file) > $mtime) || (filesize($file) != $size)) {
368                    $contents = @file($file);
369                    $tmpl = implode('', $contents);
370                }
371            }
372        }
373        return $tmpl;
374    }
375
376    function &fetch_pages($args) {
377        $args['class'] = 'page';
378        return $this->fetch_entries($args);
379    }
380
381    function &fetch_entries($args) {
382        if ($sql = $this->include_exclude_blogs($args)) {
383            $blog_filter = 'and entry_blog_id ' . $sql;
384        } elseif (isset($args['blog_id'])) {
385            $blog_id = intval($args['blog_id']);
386            $blog_filter = 'and entry_blog_id = ' . $blog_id;
387            $blog = $this->fetch_blog($blog_id);
388        }
389
390        # automatically include offset if in request
391        if ($args['offset'] == 'auto') {
392            $args['offset'] = 0;
393            if ($args['limit'] || $args['lastn']) {
394                if ($_REQUEST['offset'] > 0) {
395                    $args['offset'] = $_REQUEST['offset'];
396                }
397            }
398        }
399
400        if ($args['limit'] > 0) {
401            $args['lastn'] = $args['limit'];
402        } elseif (!isset($args['days']) && !isset($args['lastn'])) {
403            if ($days = $blog['blog_days_on_index']) {
404                if (!isset($args['recently_commented_on'])) {
405                    $args['days'] = $days;
406                }
407            } elseif ($posts = $blog['blog_entries_on_index']) {
408                $args['lastn'] = $posts;
409            }
410        }
411        if ($args['limit'] == 'auto') {
412            if (($_REQUEST['limit'] > 0) && ($_REQUEST['limit'] < $args['lastn'])) {
413                $args['lastn'] = intval($_REQUEST['limit']);
414            }
415        }
416
417        if (isset($args['include_blogs']) or isset($args['exclude_blogs'])) {
418            $blog_ctx_arg = isset($args['include_blogs']) ?
419                array('include_blogs' => $args['include_blogs']) :
420                array('exclude_blogs' => $args['exclude_blogs']);
421        }
422
423        # a context hash for filter routines
424        $ctx = array();
425        $filters = array();
426
427        if (!isset($_REQUEST['entry_ids_published'])) {
428            $_REQUEST['entry_ids_published'] = array();
429        }
430
431        if (isset($args['unique'])) {
432            $filters[] = create_function('$e,$ctx', 'return !isset($ctx["entry_ids_published"][$e["entry_id"]]);');
433            $ctx['entry_ids_published'] = &$_REQUEST['entry_ids_published'];
434        }
435
436        # special case for selecting a particular entry
437        if (isset($args['entry_id'])) {
438            $entry_filter = 'and entry_id = '.$args['entry_id'];
439            $start = ''; $end = ''; $limit = 1; $blog_filter = ''; $day_filter = '';
440        } else {
441            $entry_filter = '';
442        }
443
444        # special case for excluding a particular entry
445        if (isset($args['not_entry_id'])) {
446            $entry_filter .= ' and entry_id != '.$args['not_entry_id'];
447        }
448
449        $entry_list = array();
450
451        # Adds a category filter to the filters list.
452        $cat_class = 'category';
453        if (!isset($args['class'])) {
454            $args['class'] = 'entry';
455        }
456        if ($args['class'] == 'page') {
457            $cat_class = 'folder';
458        }
459        if (isset($args['category']) or isset($args['categories'])) {
460            $category_arg = isset($args['category']) ? $args['category'] : $args['categories'];
461            require_once("MTUtil.php");
462            if (!preg_match('/\b(AND|OR|NOT)\b|\(|\)/i', $category_arg)) {
463                $not_clause = false;
464                $cats = cat_path_to_category($category_arg, $blog_ctx_arg, $cat_class);
465                if (count($cats)) {
466                    $category_arg = '';
467                    foreach ($cats as $cat) {
468                        if ($category_arg != '')
469                            $category_arg .= '|| ';
470                        $category_arg .= '#' . $cat['category_id'];
471                    }
472                    $category_arg = '(' . $category_arg . ')';
473                }
474            } else {
475                $not_clause = preg_match('/\bNOT\b/i', $category_arg);
476                if ($blog_ctx_arg)
477                    $cats =& $this->fetch_categories(array_merge($blog_ctx_arg, array('show_empty' => 1, 'class' => $cat_class)));
478                else
479                    $cats =& $this->fetch_categories(array('blog_id' => $blog_id, 'show_empty' => 1, 'class' => $cat_class));
480            }
481            if (!is_array($cats)) $cats = array();
482            $cexpr = create_cat_expr_function($category_arg, $cats, array('children' => $args['include_subcategories']));
483            if ($cexpr) {
484                $cmap = array();
485                $cat_list = array();
486                foreach ($cats as $cat)
487                    $cat_list[] = $cat['category_id'];
488                $pl =& $this->fetch_placements(array('category_id' => $cat_list));
489                if ($pl) {
490                    foreach ($pl as $p) {
491                        $cmap[$p['placement_entry_id']][$p['placement_category_id']]++;
492                        if (!$not_clause)
493                            $entry_list[$p['placement_entry_id']] = 1;
494                    }
495                }
496                $ctx['p'] =& $cmap;
497                $filters[] = $cexpr;
498            } else {
499                return null;
500            }
501        } elseif (isset($args['category_id'])) {
502            require_once("MTUtil.php");
503            $cat = $this->fetch_category($args['category_id']);
504            if ($cat) {
505                $cats = array($cat);
506                $cmap = array();
507                $cexpr = create_cat_expr_function($cat['category_label'], $cats, array('children' => $args['include_subcategories']));
508                $pl =& $this->fetch_placements(array('category_id' => array($cat['category_id'])));
509                if ($pl) {
510                    foreach ($pl as $p) {
511                        $cmap[$p['placement_entry_id']][$p['placement_category_id']]++;
512                    }
513                    $ctx['p'] =& $cmap;
514                    $filters[] = $cexpr;
515                } else {
516                    # this category have no entries (or pages)
517                    return null;
518                }
519            }
520        }
521        if ((0 == count($filters)) && (isset($args['show_empty']) && (1 == $args['show_empty']))) {
522            return null;
523        }
524
525        # Adds a tag filter to the filters list.
526        if (isset($args['tags']) or isset($args['tag'])) {
527            $tag_arg = isset($args['tag']) ? $args['tag'] : $args['tags'];
528            require_once("MTUtil.php");
529            $not_clause = preg_match('/\bNOT\b/i', $tag_arg);
530
531            require_once("MTUtil.php");
532            $include_private = 0;
533            $tag_array = tag_split($tag_arg);
534            foreach ($tag_array as $tag) {
535                if ($tag && (substr($tag,0,1) == '@')) {
536                    $include_private = 1;
537                }
538            }
539           
540            if (isset($blog_ctx_arg))
541                $tags =& $this->fetch_entry_tags(array($blog_ctx_arg, 'tag' => $tag_arg, 'include_private' => $include_private, 'class' => $args['class']));
542            else
543                $tags =& $this->fetch_entry_tags(array('blog_id' => $blog_id, 'tag' => $tag_arg, 'include_private' => $include_private, 'class' => $args['class']));
544            if (!is_array($tags)) $tags = array();
545            $cexpr = create_tag_expr_function($tag_arg, $tags);
546
547            if ($cexpr) {
548                $tmap = array();
549                $tag_list = array();
550                foreach ($tags as $tag) {
551                    $tag_list[] = $tag['tag_id'];
552                }
553                if (isset($blog_ctx_arg))
554                    $ot =& $this->fetch_objecttags(array('tag_id' => $tag_list, 'datasource' => 'entry', $blog_ctx_arg));
555                elseif ($args['blog_id'])
556                    $ot =& $this->fetch_objecttags(array('tag_id' => $tag_list, 'datasource' => 'entry', 'blog_id' => $args['blog_id']));
557                if ($ot) {
558                    foreach ($ot as $o) {
559                            $tmap[$o['objecttag_object_id']][$o['objecttag_tag_id']]++;
560                        if (!$not_clause)
561                            $entry_list[$o['objecttag_object_id']] = 1;
562                    }
563                }
564                $ctx['t'] =& $tmap;
565                $filters[] = $cexpr;
566            } else {
567                return null;
568            }
569        }
570
571        if (count($entry_list) && ($entry_filter == '')) {
572            $entry_list = implode(",", array_keys($entry_list));
573            # set a reasonable cap on the entry list cache. if
574            # user is selecting something too big, then they'll
575            # just have to wait through a scan.
576            if (strlen($entry_list) < 2048)
577                $entry_filter = "and entry_id in ($entry_list)";
578        }
579
580        if (isset($args['author']))
581            $author_filter = 'and author_name = \'' .
582                $this->escape($args['author']) . "'";
583
584        $start = isset($args['current_timestamp'])
585            ? $args['current_timestamp'] : null;
586        $end = isset($args['current_timestamp_end'])
587            ? $args['current_timestamp_end'] : null;
588        if ($start and $end) {
589            $start = $this->ts2db($start);
590            $end = $this->ts2db($end);
591            $date_filter = "and entry_authored_on between '$start' and '$end'";
592        } elseif ($start) {
593            $start = $this->ts2db($start);
594            $date_filter = "and entry_authored_on >= '$start'";
595        } elseif ($end) {
596            $end = $this->ts2db($end);
597            $date_filter = "and entry_authored_on <= '$end'";
598        } else {
599            $date_filter = '';
600        }
601
602        if (isset($args['lastn'])) {
603            if (!isset($args['entry_id'])) $limit = $args['lastn'];
604        } elseif (isset($args['days']) && !$date_filter) {
605            $day_filter = 'and ' . $this->limit_by_day_sql('entry_authored_on', intval($args['days']));
606        } else {
607            if ((!isset($args['current_timestamp']) &&
608                !isset($args['current_timestamp_end'])) &&
609                ($limit <= 0) &&
610                (!isset($args['category'])) &&
611                (!isset($args['categories'])) &&
612                (!isset($args['category_id'])) &&
613                (isset($blog))) {
614                if ($days = $blog['blog_days_on_index']) {
615                    if (!isset($args['recently_commented_on'])) {
616                        $day_filter = 'and ' . $this->limit_by_day_sql('entry_authored_on', $days);
617                    }
618                } elseif ($posts = $blog['blog_entries_on_index']) {
619                    $limit = $posts;
620                }
621            }
622        }
623
624        if (isset($args['sort_order'])) {
625            if ($args['sort_order'] == 'ascend') {
626                $order = 'asc';
627            } else if ($args['sort_order'] == 'descend') {
628                $order = 'desc';
629            }
630        } 
631        if (!isset($order)) {
632            $order = 'desc';
633            if (isset($blog) && isset($blog['blog_sort_order_posts'])) {
634                if ($blog['blog_sort_order_posts'] == 'ascend') {
635                    $order = 'asc';
636                }
637            }
638        }
639
640        if (isset($args['class'])) {
641            $class = $this->escape($args['class']);
642        } else {
643            $class = 'entry';
644        }
645        $class_filter = "and entry_class='$class'";
646
647        if (isset($args['offset']))
648            $offset = $args['offset'];
649
650        if (isset($args['sort_by'])) {
651            if ($args['sort_by'] == 'title') {
652                $sort_field = 'entry_title';
653            } elseif ($args['sort_by'] == 'id') {
654                $sort_field = 'entry_id';
655            } elseif ($args['sort_by'] == 'status') {
656                $sort_field = 'entry_status';
657            } elseif ($args['sort_by'] == 'modified_on') {
658                $sort_field = 'entry_modified_on';
659            } elseif ($args['sort_by'] == 'author_id') {
660                $sort_field = 'entry_author_id';
661            } elseif ($args['sort_by'] == 'excerpt') {
662                $sort_field = 'entry_excerpt';
663            } elseif ($args['sort_by'] == 'comment_created_on') {
664                $sort_field = $args['sort_by'];
665            } elseif ($args['sort_by'] == 'score') {
666            } else {
667                $sort_field = 'entry_' . $args['sort_by'];
668            }
669            if ($sort_field) $no_resort = 1;
670        }
671        $sort_field or $sort_field ='entry_authored_on';
672
673        if (isset($args['limit'])) {
674            $base_order = ($args['sort_order'] == 'ascend' ? 'asc' : 'desc');
675            $base_order or $base_order = 'desc';
676        } else {
677            $base_order = 'desc';
678            if (isset($args['base_sort_order'])) {
679                if ($args['base_sort_order'] == 'ascend')
680                    $base_order = 'asc';
681            }
682            $no_resort = 0;
683        }
684
685        if (count($filters)) {
686            $post_select_limit = $limit;
687            $post_select_offset = $offset;
688            $limit = 0; $offset = 0;
689        }
690
691        $sql = "
692            select mt_entry.*, mt_placement.*, mt_author.*,
693                   mt_trackback.*
694              from mt_entry
695              left outer join mt_trackback on trackback_entry_id = entry_id
696              left outer join mt_placement on placement_entry_id = entry_id
697                   and placement_is_primary = 1,
698                   mt_author
699             where entry_status = 2
700               and entry_author_id = author_id
701                   $blog_filter
702                   $entry_filter
703                   $author_filter
704                   $date_filter
705                   $day_filter
706                   $class_filter
707             order by $sort_field $base_order
708        ";
709        if (isset($args['recently_commented_on'])) {
710            $rco = $args['recently_commented_on'];
711            $sql = $this->entries_recently_commented_on_sql($sql);
712            $sql = $this->apply_limit_sql($sql, count($filters) ? null : $rco);
713            $args['sort_by'] or $args['sort_by'] = 'comment_created_on';
714            $args['sort_order'] or $args['sort_order'] = 'descend';
715            $post_select_limit = $rco;
716            $no_resort = 1;
717        } else {
718            $sql = $this->apply_limit_sql($sql . " <LIMIT>", $limit, $offset);
719        }
720
721        $result = $this->query_start($sql);
722        if (!$result) return null;
723
724        $entries = array();
725        $j = 0;
726        $offset = $post_select_offset ? $post_select_offset : 0;
727        $limit = $post_select_limit ? $post_select_limit : 0;
728        $id_list = array();
729        while (true) {
730            $e = $this->query_fetch(ARRAY_A);
731            if (!isset($e)) break;
732            if (count($filters)) {
733                foreach ($filters as $f) {
734                    if (!$f($e, $ctx)) continue 2;
735                }
736            }
737            if ($offset && ($j++ < $offset)) continue;
738            $e['entry_authored_on'] = $this->db2ts($e['entry_authored_on']);
739            $e['entry_modified_on'] = $this->db2ts($e['entry_modified_on']);
740            $id_list[] = $e['entry_id'];
741            $entries[] = $e;
742            if (($limit > 0) && (count($entries) >= $limit)) break;
743        }
744
745        if (!$no_resort) {
746            $sort_field = '';
747            if (isset($args['sort_by'])) {
748                if ($args['sort_by'] == 'title') {
749                    $sort_field = 'entry_title';
750                } elseif ($args['sort_by'] == 'id') {
751                    $sort_field = 'entry_id';
752                } elseif ($args['sort_by'] == 'status') {
753                    $sort_field = 'entry_status';
754                } elseif ($args['sort_by'] == 'modified_on') {
755                    $sort_field = 'entry_modified_on';
756                } elseif ($args['sort_by'] == 'author_id') {
757                    $sort_field = 'entry_author_id';
758                } elseif ($args['sort_by'] == 'excerpt') {
759                    $sort_field = 'entry_excerpt';
760                } elseif ($args['sort_by'] == 'comment_created_on') {
761                    $sort_field = $args['sort_by'];
762                } elseif ($args['sort_by'] == 'score') {
763                    $sort_field = $args['sort_by'];
764                } else {
765                    $sort_field = 'entry_' . $args['sort_by'];
766                }
767            } else {
768                $sort_field = 'entry_authored_on';
769            }
770            if ($sort_field) {
771                if ($sort_field == 'score') {
772                    $entries_tmp = array();
773                    foreach ($entries as $e) {
774                        $entries_tmp[$e['entry_id']] = $e;
775                    }
776                    $scores = $this->fetch_sum_scores($args['namespace'], 'entry', $order,
777                        $blog_filter . "\n" .
778                        $entry_filter . "\n" .
779                        $author_filter . "\n" .
780                        $date_filter . "\n" .
781                        $day_filter . "\n" .
782                        $class_filter . "\n"
783                    );
784                    $entries_sorted = array();
785                    foreach($scores as $score) {
786                        if (array_key_exists($score['objectscore_object_id'], $entries_tmp)) {
787                            array_push($entries_sorted, $entries_tmp[$score['objectscore_object_id']]);
788                            unset($entries_tmp[$score['objectscore_object_id']]);
789                        }
790                    }
791                    foreach ($entries_tmp as $et) {
792                        array_push($entries_sorted, $et);
793                    }
794                    $entries = $entries_sorted;
795                } else {
796                    if (($sort_field == 'entry_status') || ($sort_field == 'entry_author_id') || ($sort_field == 'entry_id')) {
797                        $sort_fn = "if (\$a['$sort_field'] == \$b['$sort_field']) return 0; return \$a['$sort_field'] < \$b['$sort_field'] ? -1 : 1;";
798                    } else {
799                        $sort_fn = "return strcmp(\$a['$sort_field'],\$b['$sort_field']);";
800                    }
801                    $sorter = create_function(
802                        $order == 'asc' ? '$a,$b' : '$b,$a',
803                        $sort_fn);
804                    usort($entries, $sorter);
805                }
806            }
807        }
808
809        if (count($id_list) <= 30) { # TODO: find a good upper limit
810            # pre-cache comment counts and categories for these entries
811            $this->cache_comment_counts($id_list);
812            $this->cache_ping_counts($id_list);
813            $this->cache_categories($id_list);
814            $this->cache_permalinks($id_list);
815        }
816
817        return $entries;
818    }
819
820    function fetch_plugin_config($plugin, $scope = "system") {
821        if ($scope != 'system') {
822            $key = 'configuration:'.$scope;
823        } else {
824            $key = 'configuration';
825        }
826        return $this->fetch_plugin_data($plugin, $key);
827    }
828
829    function fetch_plugin_data($plugin, $key) {
830        $plugin = $this->escape($plugin);
831        $key = $this->escape($key);
832        $sql = "
833            select plugindata_data from mt_plugindata
834             where plugindata_plugin = '$plugin'
835               and plugindata_key = '$key'";
836        $data = $this->get_var($sql);
837        if ($data) {
838            return $this->unserialize($data);
839        }
840        return null;
841    }
842
843    function &fetch_entry_tags($args) {
844        $class = 'entry';
845        if (isset($args['class'])) {
846            $class = $args['class'];
847        }
848
849        # load tags
850        if (isset($args['entry_id'])) {
851            if (!isset($args['tags']) && !isset($args['tag'])) {
852                if (isset($this->_entry_tag_cache[$args['entry_id']])) {
853                    return $this->_entry_tag_cache[$args['entry_id']];
854                }
855            }
856            $entry_filter = 'and objecttag_tag_id in (select objecttag_tag_id from mt_objecttag where objecttag_object_id='.intval($args['entry_id']).')';
857        }
858
859        $blog_filter = $this->include_exclude_blogs($args);
860        if ($blog_filter == '' and isset($args['blog_id'])) {
861            if (!isset($args['tags']) && !isset($args['tag'])) {
862                if (!isset($args['entry_id'])) {
863                    if (isset($this->_blog_tag_cache[$args['blog_id'].":$class"])) {
864                        return $this->_blog_tag_cache[$args['blog_id'].":$class"];
865                    }
866                }
867            }
868            $blog_filter = ' = '. intval($args['blog_id']);
869        }
870        if ($blog_filter != '') 
871            $blog_filter = 'and objecttag_blog_id ' . $blog_filter;
872
873        if (!isset($args['include_private'])) {
874            $private_filter = 'and (tag_is_private = 0 or tag_is_private is null)';
875        }
876        if (isset($args['tags']) && ($args['tags'] != '')) {
877            $tag_list = '';
878            require_once("MTUtil.php");
879            $tag_array = tag_split($args['tags']);
880            foreach ($tag_array as $tag) {
881                if ($tag_list != '') $tag_list .= ',';
882                $tag_list .= "'" . $this->escape($tag) . "'";
883            }
884            if ($tag_list != '') {
885                $tag_filter = 'and (tag_name in (' . $tag_list . '))';
886                $private_filter = '';
887            }
888        }
889
890        $sort_col = isset($args['sort_by']) ? $args['sort_by'] : 'name';
891        $sort_col = "tag_$sort_col";
892        if (isset($args['sort_order']) and $args['sort_order'] == 'descend') {
893            $order = 'desc';
894        } else {
895            $order = 'asc';
896        }
897        $id_order = '';
898        if ($sort_col == 'tag_name') {
899            $sort_col = 'lower(tag_name)';
900        }else{
901            $id_order = ', lower(tag_name)';
902        }
903
904        $sql = "
905            select tag_id, tag_name, count(*) as tag_count
906             from mt_tag, mt_objecttag, mt_entry
907             where objecttag_tag_id = tag_id
908               and entry_id = objecttag_object_id and objecttag_object_datasource='entry'
909               and entry_status = 2
910                   and entry_class = '$class'
911                   $blog_filter
912                   $tag_filter
913                   $entry_filter
914                   $private_filter
915            group by tag_id, tag_name
916            order by $sort_col $order $id_order";
917        $tags = $this->get_results($sql, ARRAY_A);
918        if (!isset($args['tag'])) {
919            if ($args['entry_id'])
920                $this->_entry_tag_cache[$args['entry_id']] = $tags;
921            elseif ($args['blog_id'])
922                $this->_blog_tag_cache[$args['blog_id'].":$class"] = $tags;
923        }
924        return $tags;
925    }
926
927    function &fetch_asset_tags($args) {
928
929        # load tags by asset
930        if (!isset($args['include_private'])) {
931            $private_filter = 'and (tag_is_private = 0 or tag_is_private is null)';
932        }
933
934        if (isset($args['asset_id'])) {
935            if (isset($args['tags'])) {
936                if (isset($this->_asset_tag_cache[$args['asset_id']]))
937                    return $this->_asset_tag_cache[$args['asset_id']];
938            }
939            $asset_filter = 'and objecttag_object_id = '.intval($args['asset_id']);
940        }
941       
942        if (isset($args['blog_id'])) {
943            if (!isset($args['tags'])) {
944                if (isset($this->_blog_asset_tag_cache[$args['blog_id']]))
945                    return $this->_blog_asset_tag_cache[$args['blog_id']];
946            }
947            $blog_filter = 'and objecttag_blog_id = '.intval($args['blog_id']);
948        }
949
950        if (isset($args['tags']) && ($args['tags'] != '')) {
951            $tag_list = '';
952            require_once("MTUtil.php");
953            $tag_array = tag_split($args['tags']);
954            foreach ($tag_array as $tag) {
955                if ($tag_list != '') $tag_list .= ',';
956                $tag_list .= "'" . $this->escape($tag) . "'";
957            }
958            if ($tag_list != '') {
959                $tag_filter = 'and (tag_name in (' . $tag_list . '))';
960                $private_filter = '';
961            }
962        }
963
964        $sort_col = isset($args['sort_by']) ? $args['sort_by'] : 'name';
965        $sort_col = "tag_$sort_col";
966        if (isset($args['sort_order']) and $args['sort_order'] == 'descend')
967            $order = 'desc';
968        else
969            $order = 'asc';
970
971        $id_order = '';
972        if ($sort_col == 'tag_name')
973            $sort_col = 'lower(tag_name)';
974        else
975            $id_order = ', lower(tag_name)';
976
977        $sql = "
978            select tag_id, tag_name, count(*) as tag_count
979            from mt_tag, mt_objecttag, mt_asset
980            where objecttag_tag_id = tag_id
981                and asset_id = objecttag_object_id and objecttag_object_datasource='asset'
982                $blog_filter
983                $private_filter
984                $tag_filter
985                $asset_filter
986            group by tag_id, tag_name
987            order by $sort_col $order $id_order
988        ";
989        $tags = $this->get_results($sql, ARRAY_A);
990        if (isset($args['tags'])) {
991            if ($args['asset_id'])
992                $this->_asset_tag_cache[$args['asset_id']] = $tags;
993            elseif ($args['blog_id'])
994                $this->_blog_asset_tag_cache[$args['blog_id']] = $tags;
995        }
996        return $tags;
997    }
998
999    function &fetch_folders($args) {
1000        $args['class'] = 'folder';
1001        return $this->fetch_categories($args);
1002    }
1003
1004    function &fetch_categories($args) {
1005        # load categories
1006
1007        if ($blog_filter = $this->include_exclude_blogs($args)) {
1008             $blog_filter = 'and category_blog_id '. $blog_filter;
1009        } elseif (isset($args['blog_id'])) {
1010            $blog_filter = 'and category_blog_id = '.intval($args['blog_id']);
1011        }
1012        if (isset($args['parent'])) {
1013            $parent = $args['parent'];
1014            if (is_array($parent)) {
1015                $parent_filter = 'and category_parent in (' . implode(',', $parent) . ')';
1016            } else {
1017                $parent_filter = 'and category_parent = '.intval($parent);
1018            }
1019        }
1020        if (isset($args['category_id'])) {
1021            if (isset($args['children'])) {
1022                if (isset($this->_cat_id_cache['c'.$args['category_id']])) {
1023                    $cat = $this->_cat_id_cache['c'.$args['category_id']];
1024                    if (isset($cat['_children'])) {
1025                        $children = $cat['_children'];
1026                        if ($children === false) {
1027                            return null;
1028                        } else {
1029                            return $children;
1030                        }
1031                    }
1032                }
1033
1034                $cat_filter = 'and category_parent = '.intval($args['category_id']);
1035            } else {
1036                $cat_filter = 'and category_id = '.intval($args['category_id']);
1037                $limit = 1;
1038            }
1039        } elseif (isset($args['label'])) {
1040            $cat_filter = 'and category_label = \''.$this->escape($args['label']).'\'';
1041        } else {
1042            $limit = $args['lastn'];
1043            if (isset($args['sort_order'])) {
1044                if ($args['sort_order'] == 'ascend') {
1045                    $sort_order = 'asc';
1046                } elseif ($args['sort_order'] == 'descend') {
1047                    $sort_order = 'desc';
1048                }
1049            } else {
1050                $sort_order = '';
1051            }
1052        }
1053        $count_column = 'placement_id';
1054        if ($args['show_empty']) {
1055            $join_clause = 'left outer join mt_placement on placement_category_id = category_id';
1056            if (isset($args['entry_id'])) {
1057                $join_clause .= ' left outer join mt_entry on placement_entry_id = entry_id and entry_id = '.intval($args['entry_id']);
1058            } else {
1059                $join_clause .= ' left outer join mt_entry on placement_entry_id = entry_id and entry_status = 2';
1060            }
1061            $count_column = 'entry_id';
1062        } else {
1063            $join_clause = ', mt_entry, mt_placement';
1064            $cat_filter .= ' and placement_category_id = category_id';
1065            if (isset($args['entry_id'])) {
1066                $entry_filter = 'and placement_entry_id = entry_id and placement_entry_id = '.intval($args['entry_id']);
1067            } else {
1068                $entry_filter = 'and placement_entry_id = entry_id and entry_status = 2';
1069            }
1070        }
1071
1072        if (isset($args['class'])) {
1073            $class = $this->escape($args['class']);
1074        } else {
1075            $class = "category";
1076        }
1077        $class_filter = "and category_class='$class'";
1078
1079        $sql = "
1080            select category_id, count($count_column) as category_count
1081              from mt_category $join_clause
1082             where 1 = 1
1083                   $cat_filter
1084                   $entry_filter
1085                   $blog_filter
1086                   $parent_filter
1087                   $class_filter
1088             group by category_id
1089                   <LIMIT>
1090        ";
1091        $sql = $this->apply_limit_sql($sql, $limit, $offset);
1092
1093        $categories = $this->get_results($sql, ARRAY_A);
1094        if (!$categories) {
1095            return null;
1096        }
1097        if (isset($args['children']) && isset($parent_cat)) {
1098            $parent_cat['_children'] =& $categories;
1099        } else {
1100            $ids = array();
1101            $counts = array();
1102            foreach ($categories as $cid => $cat) {
1103                $counts[$cat['category_id']] = $cat['category_count'];
1104                $ids[] = $cat['category_id'];
1105            }
1106            $list = implode(",", $ids);
1107            $sql2 = "
1108                select mt_category.*, mt_trackback.*
1109                    from mt_category left outer join mt_trackback on trackback_category_id = category_id
1110                   where category_id in ($list)
1111                order by category_label $sort_order
1112            ";
1113            $categories = $this->get_results($sql2, ARRAY_A);
1114            $id_list = array();
1115            foreach ($categories as $cid => $cat) {
1116                $cat_id = $cat['category_id'];
1117                $categories[$cid]['category_count'] = $counts[$cat_id];
1118                if (isset($args['top_level_categories']) || !isset($this->_cat_id_cache['c'.$cat_id])) {
1119                    $id_list[] = $cat_id;
1120                    $this->_cat_id_cache['c'.$cat_id] = $categories[$cid];
1121                }
1122                if (isset($args['top_level_categories'])) {
1123                    $this->_cat_id_cache['c'.$cat_id]['_children'] = false;
1124                }
1125            }
1126
1127            $top_cats = array();
1128            foreach ($categories as $cid => $cat) {
1129                if ($cat['category_parent'] > 0) {
1130                    $parent_id = $cat['category_parent'];
1131                    if (isset($this->_cat_id_cache['c'.$parent_id])) {
1132                        if (isset($args['top_level_categories'])) {
1133                            $parent =& $this->fetch_category($categories[$cid]['category_parent']);
1134                            if (!isset($parent['_children']) || ($parent['_children'] === false)) {
1135                                $parent['_children'] = array(&$categories[$cid]);
1136                            } else {
1137                                $parent['_children'][] = $categories[$cid];
1138                            }
1139                        }
1140                    }
1141                }
1142                if ((!$cat['category_parent']) && (isset($args['top_level_categories']))) {
1143                    $top_cats[] = $categories[$cid];
1144                }
1145            }
1146            $this->cache_category_links($id_list);
1147            if (isset($args['top_level_categories'])) {
1148                return $top_cats;
1149            }
1150        }
1151        return $categories;
1152    }
1153
1154    function &fetch_entry($entry_id) {
1155        if (isset($this->_entry_id_cache['entry_id'])) {
1156            return $this->_entry_id_cache[$entry_id];
1157        }
1158        list($entry) = $this->fetch_entries(array('entry_id' => $entry_id));
1159        $this->_entry_id_cache[$entry_id] = $entry;
1160        return $entry;
1161    }
1162
1163    function &fetch_page($entry_id) {
1164        if (isset($this->_entry_id_cache['entry_id'])) {
1165            return $this->_entry_id_cache[$entry_id];
1166        }
1167        list($entry) = $this->fetch_pages(array('entry_id' => $entry_id));
1168        $this->_entry_id_cache[$entry_id] = $entry;
1169        return $entry;
1170    }
1171
1172    function &fetch_author($author_id) {
1173        if (isset($this->_author_id_cache[$author_id])) {
1174            return $this->_author_id_cache[$author_id];
1175        }
1176        global $mt;
1177        $args['blog_id'] = $mt->blog_id;
1178        $args['author_id'] = $author_id;
1179        $result = $this->fetch_authors($args);
1180        $author = null;
1181        if (is_array($result)) {
1182            $author = $result[0];
1183            $this->_author_id_cache[$author_id] = $author;
1184        }
1185        return $author;
1186    }
1187
1188    function &fetch_authors($args) {
1189        # make filters
1190        $filters = array();
1191
1192        $extend_column = '';
1193        # Adds blog filter
1194
1195        if ($sql = $this->include_exclude_blogs($args)) {
1196            $blog_filter = 'join mt_permission on permission_author_id = author_id and permission_blog_id ' . $sql;
1197            $extend_column = ', mt_permission.*';
1198        } elseif (isset($args['blog_id'])) {
1199            $blog_id = intval($args['blog_id']);
1200            $blog_filter = "join mt_permission on permission_author_id = author_id and permission_blog_id = $blog_id";
1201            $extend_column = ', mt_permission.*';
1202        }
1203
1204        # Adds author filter
1205        if (isset($args['author_id'])) {
1206            $author_id = intval($args['author_id']);
1207            array_push($filters, "author_id = $author_id");
1208        }
1209        if (isset($args['author_nickname'])) {
1210            array_push($filters, "author_nickname = '".$args['author_nickname']."'");
1211        }
1212
1213        # Adds entry filter
1214        if ($args['need_entry']) {
1215            $entry_filter = 'join mt_entry on author_id = entry_author_id';
1216            $unique_filter = 'distinct';
1217            array_push($filters, "entry_status = 2");
1218            if ($blog_filter) {
1219                array_push($filters, "entry_blog_id = permission_blog_id");
1220            } else {
1221                array_push($filters, "entry_blog_id = ".$args['blog_id']);
1222            }
1223        }
1224
1225        # sort
1226        if (isset($args['sort_by'])) {
1227            $sort_col = $args['sort_by'];
1228            $order = '';
1229            if (isset($args['sort_order'])) {
1230                if ($args['sort_order'] == 'ascend')
1231                    $order = 'asc';
1232                else
1233                    $order = 'desc';
1234            }
1235            $order_sql = "order by $sort_col $order";
1236
1237            if (isset($args['start_string'])) {
1238                $val = $args['start_string'];
1239                if ($order == 'asc')
1240                    $val_order = '>';
1241                else
1242                    $val_order = '<';
1243                array_push($filters, "$sort_col $val_order '$val'");
1244            }
1245
1246            if (isset($args['start_num'])) {
1247                $val = $args['start_num'];
1248                if ($order == 'asc')
1249                    $val_order = '>';
1250                else
1251                    $val_order = '<';
1252                array_push($filters, "$sort_col $val_order $val");
1253            }
1254        }
1255
1256        # implode filters
1257        $filter = implode(' and ', $filters);
1258        if ($filter != '') {
1259            $filter = "where $filter";
1260        }
1261
1262        $sql = "
1263            select $unique_filter
1264                   mt_author.*
1265                   $extend_column
1266              from mt_author
1267                   $blog_filter
1268                   $entry_filter
1269              $filter
1270              $order_sql
1271                   <LIMIT>
1272        ";
1273        $sql = $this->apply_limit_sql($sql, $args['lastn'], $args['offset']);
1274        $results = $this->get_results($sql, ARRAY_A);
1275        return $results;
1276    }
1277
1278    function &fetch_tag($tag_id) {
1279        $tag_id = intval($tag_id);
1280        if (isset($this->_tag_id_cache[$tag_id])) {
1281            return $this->_tag_id_cache[$tag_id];
1282        }
1283        $tag = $this->get_row("
1284            select *
1285              from mt_tag
1286             where tag_id=$tag_id
1287        ", ARRAY_A);
1288        $this->_tag_id_cache[$tag_id] = $tag;
1289        return $tag;
1290    }
1291
1292    function &fetch_tag_by_name($tag_name) {
1293        $tag_name = $this->escape($tag_name);
1294        $tag = $this->get_row("
1295            select *
1296              from mt_tag
1297             where tag_name='$tag_name'
1298        ", ARRAY_A);
1299        $this->_tag_id_cache[$tag['tag_id']] = $tag;
1300        return $tag;
1301    }
1302
1303    function fetch_scores($namespace, $obj_id, $datasource) {
1304        $scores = $this->get_results("
1305            select * from mt_objectscore
1306            where objectscore_namespace='$namespace'
1307            and objectscore_object_id='$obj_id'
1308            and objectscore_object_ds='$datasource'
1309        ", ARRAY_A);
1310        return $scores;
1311    }
1312
1313    function fetch_score($namespace, $obj_id, $user_id, $datasource) {
1314        list($score) = $this->get_results("
1315            select * from mt_objectscore
1316            where objectscore_namespace='$namespace'
1317            and objectscore_object_id='$obj_id'
1318            and objectscore_object_ds='$datasource'
1319            and objectscore_user_id='$user_id'
1320        ", ARRAY_A);
1321        return $score;
1322    }
1323
1324    function fetch_sum_scores($namespace, $datasource, $order, $filters) {
1325        $othertables = '';
1326        $otherwhere = '';
1327        if ($datasource == 'asset') {
1328            $othertables = ', mt_author';
1329            $otherwhere = 'AND (objectscore_author_id = author_id)';
1330        }
1331        $join_column = $datasource . '_id';
1332        $join_where = "AND ($join_column = objectscore_object_id)";
1333        $sql_scores = 
1334            "SELECT SUM(objectscore_score) AS sum_objectscore_score, objectscore_object_id
1335             FROM mt_objectscore, mt_$datasource $othertables
1336             WHERE (objectscore_namespace = '$namespace')
1337             AND (objectscore_object_ds = '$datasource')
1338             $join_where
1339             $otherwhere
1340             $filters
1341             GROUP BY objectscore_object_id
1342             ORDER BY sum_objectscore_score " . $order;
1343        $scores = $this->get_results($sql_scores, ARRAY_A);
1344        return $scores;
1345    }
1346
1347    function cache_permalinks(&$entry_list) {
1348        $id_list = '';
1349        foreach ($entry_list as $entry_id) {
1350            if (!isset($this->_entry_link_cache[$entry_id.';Individual'])) {
1351                $id_list .= ','.$entry_id;
1352                $this->_entry_link_cache[$entry_id.';Individual'] = ''; 
1353            }
1354        }
1355        if (empty($id_list))
1356            return;
1357        $id_list = substr($id_list, 1);
1358        $query = "
1359            select fileinfo_entry_id, fileinfo_url, blog_site_url, blog_file_extension
1360              from mt_fileinfo, mt_templatemap, mt_blog
1361             where fileinfo_entry_id in ($id_list)
1362               and fileinfo_archive_type = 'Individual'
1363               and blog_id = fileinfo_blog_id
1364               and templatemap_id = fileinfo_templatemap_id
1365               and templatemap_is_preferred = 1
1366        ";
1367        $results = $this->get_results($query, ARRAY_N);
1368        if ($results) {
1369
1370            foreach ($results as $row) {
1371                $blog_url = $row[2];
1372                $blog_url = preg_replace('!(https?://(?:[^/]+))/.*!', '$1', $blog_url);
1373                $url = $blog_url . $row[1];
1374                $url = _strip_index($url, array('blog_file_extension' => $row[3]));
1375                $this->_entry_link_cache[$row[0].';Individual'] = $url;
1376            }
1377        }
1378    }
1379
1380    function cache_category_links(&$cat_list) {
1381        $id_list = '';
1382        foreach ($cat_list as $cat_id) {
1383            if (!isset($this->_cat_link_cache[$cat_id])) {
1384                $id_list .= ','.$cat_id;
1385                $this->_cat_link_cache[$cat_id] = '';
1386            }
1387        }
1388        if (empty($id_list))
1389            return;
1390        $id_list = substr($id_list, 1);
1391        $query = "
1392            select fileinfo_category_id, fileinfo_url, blog_site_url, blog_file_extension
1393              from mt_fileinfo, mt_templatemap, mt_blog
1394             where fileinfo_category_id in ($id_list)
1395               and fileinfo_archive_type = 'Category'
1396               and blog_id = fileinfo_blog_id
1397               and templatemap_id = fileinfo_templatemap_id
1398               and templatemap_is_preferred = 1
1399        ";
1400        $results = $this->get_results($query, ARRAY_N);
1401        if ($results) {
1402            foreach ($results as $row) {
1403                $blog_url = $row[2];
1404                $blog_url = preg_replace('!(https?://(?:[^/]+))/.*!', '$1', $blog_url);
1405                $url = $blog_url . $row[1];
1406                $url = _strip_index($url, array('blog_file_extension' => $row[3]));
1407                $this->_cat_link_cache[$row[0]] = $url;
1408            }
1409        }
1410    }
1411
1412    function cache_comment_counts(&$entry_list) {
1413        $id_list = '';
1414        foreach ($entry_list as $entry_id) {
1415            if (!isset($this->_comment_count_cache[$entry_id])) {
1416                $id_list .= ','.$entry_id;
1417                $this->_comment_count_cache[$entry_id] = 0;
1418            }
1419        }
1420        if (empty($id_list))
1421            return;
1422        $id_list = substr($id_list, 1);
1423        $query = "
1424            select comment_entry_id, count(*)
1425              from mt_comment
1426             where comment_entry_id in ($id_list)
1427               and comment_visible = 1
1428             group by comment_entry_id
1429        ";
1430        $results = $this->get_results($query, ARRAY_N);
1431        if ($results) {
1432            foreach ($results as $row) {
1433                $this->_comment_count_cache[$row[0]] = $row[1];
1434            }
1435        }
1436    }
1437
1438    function blog_entry_count($args) {
1439
1440        if ($sql = $this->include_exclude_blogs($args)) {
1441            $blog_filter = 'and entry_blog_id ' . $sql;
1442        } elseif (isset($args['blog_id'])) {
1443            $blog_id = intval($args['blog_id']);
1444            $blog_filter = 'and entry_blog_id = ' . $blog_id;
1445        }
1446        $class = 'entry';
1447        if (isset($args['class'])) {
1448            $class = $args['class'];
1449        }
1450        $count = $this->get_var("
1451          select count(*)
1452            from mt_entry
1453            where entry_status = 2
1454            and entry_class='$class'
1455            $blog_filter
1456            ");
1457        return $count;
1458    }
1459
1460    function blog_comment_count($args) {
1461
1462        if ($sql = $this->include_exclude_blogs($args)) {
1463            $blog_filter = 'and comment_blog_id ' . $sql;
1464        } elseif (isset($args['blog_id'])) {
1465            $blog_id = intval($args['blog_id']);
1466            $blog_filter = 'and comment_blog_id = ' . $blog_id;
1467        }
1468
1469        $count = $this->get_var("
1470            select count(*)
1471              from mt_entry, mt_comment
1472             where entry_status = 2
1473               and comment_visible = 1
1474               and comment_entry_id = entry_id
1475               $blog_filter
1476        ");
1477        return $count;
1478    }
1479
1480    function blog_ping_count($args) {
1481
1482        if ($sql = $this->include_exclude_blogs($args)) {
1483            $blog_filter = 'and tbping_blog_id ' . $sql;
1484        } elseif (isset($args['blog_id'])) {
1485            $blog_id = intval($args['blog_id']);
1486            $blog_filter = 'and tbping_blog_id = ' . $blog_id;
1487        }
1488
1489        $count = $this->get_var("
1490            select count(*)
1491              from mt_tbping, mt_trackback
1492             where tbping_visible = 1
1493               and tbping_tb_id = trackback_id
1494                   $blog_filter
1495        ");
1496        return $count;
1497    }
1498
1499    function blog_category_count($args) {
1500
1501        if ($sql = $this->include_exclude_blogs($args)) {
1502            $blog_filter = 'and category_blog_id ' . $sql;
1503        } elseif (isset($args['blog_id'])) {
1504            $blog_id = intval($args['blog_id']);
1505            $blog_filter = 'and category_blog_id = ' . $blog_id;
1506        }
1507        $count = $this->get_var("
1508            select count(*)
1509              from mt_category
1510             where 1 = 1
1511             $blog_filter
1512        ");
1513        return $count;
1514    }
1515
1516    function tags_entry_count($tag_id) {
1517        $count = $this->get_var("
1518          select count(*)
1519            from mt_objecttag, mt_entry
1520           where objecttag_tag_id = " . intval($tag_id) . "
1521             and entry_id = objecttag_object_id and objecttag_object_datasource='entry'
1522             and entry_status = 2
1523        ");
1524        return $count;
1525    }
1526
1527    function entry_comment_count($entry_id) {
1528        if (isset($this->_comment_count_cache[$entry_id])) {
1529            return $this->_comment_count_cache[$entry_id];
1530        }
1531        $count = $this->get_var("
1532            select count(*)
1533              from mt_comment
1534             where comment_entry_id = " . intval($entry_id) . "
1535               and comment_visible = 1
1536        ");
1537        $this->_comment_count_cache[$entry_id] = $count;
1538        return $count;
1539    }
1540
1541    function &fetch_placements($args) {
1542        $category_id_list = $args['category_id'];
1543        $id_list = '';
1544        foreach ($category_id_list as $cat_id) {
1545            $id_list .= ',' . $cat_id;
1546        }
1547        if (empty($id_list))
1548            return;
1549        $id_list = substr($id_list, 1);
1550        $sql = "
1551            select mt_placement.*
1552              from mt_placement, mt_entry
1553              where placement_category_id in ($id_list)
1554               and entry_id = placement_entry_id and entry_status = 2
1555        ";
1556        $results = $this->get_results($sql, ARRAY_A);
1557        return $results;
1558    }
1559
1560    function &fetch_objecttags($args) {
1561        $tag_id_list = $args['tag_id'];
1562        $id_list = '';
1563        foreach ($tag_id_list as $tag_id) {
1564            $id_list .= ',' . $tag_id;
1565        }
1566        if (empty($id_list))
1567            return;
1568        $id_list = substr($id_list, 1);
1569
1570        $blog_filter = $this->include_exclude_blogs($args);
1571        if ($blog_filter == '' and $args['blog_id'])
1572            $blog_filter = intval($args['blog_id']);
1573        if ($blog_filter != '') 
1574            $blog_filter = 'and objecttag_blog_id = ' . $blog_filter;
1575
1576        $sql = "
1577            select mt_objecttag.*
1578              from mt_objecttag, mt_entry
1579              where objecttag_tag_id in ($id_list)
1580                $blog_filter
1581                and entry_id = objecttag_object_id
1582                and entry_status = 2
1583        ";
1584        $results = $this->get_results($sql, ARRAY_A);
1585        return $results;
1586    }
1587
1588    function &fetch_comments($args) {
1589        $entry_id = intval($args['entry_id']);
1590
1591        $sql = $this->include_exclude_blogs($args);
1592        if ($sql != '') {
1593            $blog_filter = 'and comment_blog_id ' . $sql;
1594            if (isset($args['blog_id']))
1595                $blog =& $this->fetch_blog($args['blog_id']);
1596        } elseif ($args['blog_id']) {
1597            $blog =& $this->fetch_blog($args['blog_id']);
1598            $blog_filter = ' and comment_blog_id = ' . $blog['blog_id'];
1599        }
1600        # load comments
1601
1602        $order = 'desc';
1603        if (isset($args['sort_order'])) {
1604            if ($args['sort_order'] == 'ascend') {
1605                $order = 'asc';
1606            }
1607        } elseif (isset($blog) && isset($blog['blog_sort_order_comments'])) {
1608            if ($blog['blog_sort_order_comments'] == 'ascend') {
1609                $order = 'asc';
1610            }
1611        }
1612        if ($order == 'asc' && $args['lastn']) {
1613            $reorder = 1;
1614            $order = 'desc';
1615        }
1616        if ($entry_id) {
1617            $entry_filter = " and comment_entry_id = $entry_id";
1618        } else {
1619            $entry_join = "join mt_entry on entry_id = comment_entry_id and entry_status = 2";
1620        }
1621        $sql = "
1622            select *
1623              from mt_comment
1624                   $entry_join
1625             where 1 = 1
1626                   $entry_filter
1627                   $blog_filter
1628               and comment_visible = 1
1629             order by comment_created_on $order
1630                   <LIMIT>";
1631        $sql = $this->apply_limit_sql($sql, $args['lastn'], $args['offset']);
1632        $comments = $this->get_results($sql, ARRAY_A);
1633        if (!is_array($comments))
1634            return array();
1635
1636        if ($reorder) {  // lastn and ascending sort
1637            $asc_created_on = create_function('$a,$b', 'return strcmp($a["comment_created_on"], $b["comment_created_on"]);');
1638            usort($comments, $asc_created_on);
1639        }
1640 
1641        return $comments;
1642    }
1643
1644    function &fetch_comment_parent($args) {
1645        if (!$args['parent_id']) {
1646            return array();
1647        }
1648        $parent_id = intval($args['parent_id']);
1649
1650        $sql = $this->include_exclude_blogs($args);
1651        if ($sql != '') {
1652            $blog_filter = 'and comment_blog_id ' . $sql;
1653            if (isset($args['blog_id']))
1654                $blog =& $this->fetch_blog($args['blog_id']);
1655        } elseif ($args['blog_id']) {
1656            $blog =& $this->fetch_blog($args['blog_id']);
1657            $blog_filter = ' and comment_blog_id = ' . $blog['blog_id'];
1658        }
1659
1660        $sql = "
1661            select *
1662              from mt_comment
1663             where 1 = 1
1664                   $blog_filter
1665               and comment_id = $parent_id
1666               and comment_visible = 1
1667        ";
1668        $comment = $this->get_results($sql, ARRAY_A);
1669
1670        return $comment;
1671    }
1672
1673    function &fetch_comment_replies($args) {
1674        if (!$args['comment_id']) {
1675            return array();
1676        }
1677        $comment_id = intval($args['comment_id']);
1678
1679        $sql = $this->include_exclude_blogs($args);
1680        if ($sql != '') {
1681            $blog_filter = 'and comment_blog_id ' . $sql;
1682            if (isset($args['blog_id']))
1683                $blog =& $this->fetch_blog($args['blog_id']);
1684        } elseif ($args['blog_id']) {
1685            $blog =& $this->fetch_blog($args['blog_id']);
1686            $blog_filter = ' and comment_blog_id = ' . $blog['blog_id'];
1687        }
1688
1689        $order = 'asc';
1690        if (isset($args['sort_order'])) {
1691            if ($args['sort_order'] == 'descend') {
1692                $order = 'desc';
1693            }
1694        } elseif (isset($blog) && isset($blog['blog_sort_order_comments'])) {
1695            if ($blog['blog_sort_order_comments'] == 'ascend') {
1696                $order = 'asc';
1697            }
1698        }
1699        if ($order == 'asc' && $args['lastn']) {
1700            $reorder = 1;
1701            $order = 'desc';
1702        }
1703        $sql = "
1704            select *
1705              from mt_comment
1706             where 1 = 1
1707                   $blog_filter
1708               and comment_parent_id = $comment_id
1709               and comment_visible = 1
1710             order by comment_created_on $order
1711                   <LIMIT>";
1712        $sql = $this->apply_limit_sql($sql, $args['lastn'], $args['offset']);
1713        $comments = $this->get_results($sql, ARRAY_A);
1714        if (!is_array($comments))
1715            return array();
1716
1717        if ($reorder) {  // lastn and ascending sort
1718            $asc_created_on = create_function('$a,$b', 'return strcmp($a["comment_created_on"], $b["comment_created_on"]);');
1719            usort($comments, $asc_created_on);
1720        }
1721 
1722        return $comments;
1723    }
1724
1725    function cache_ping_counts(&$entry_list) {
1726        $id_list = '';
1727        foreach ($entry_list as $entry_id) {
1728            if (!isset($this->_ping_count_cache[$entry_id])) {
1729                $id_list .= ','.$entry_id;
1730                $this->_ping_count_cache[$entry_id] = 0;
1731            }
1732        }
1733        $id_list = substr($id_list, 1);
1734        if (empty($id_list))
1735            return;
1736        $query = "
1737            select trackback_entry_id, count(*)
1738              from mt_trackback, mt_tbping
1739             where trackback_entry_id in ($id_list)
1740               and tbping_tb_id = trackback_id
1741               and tbping_visible = 1
1742             group by trackback_entry_id
1743        ";
1744        $results = $this->get_results($query, ARRAY_N);
1745        if ($results) {
1746            foreach ($results as $row) {
1747                $this->_ping_count_cache[$row[0]] = $row[1];
1748            }
1749        }
1750    }
1751
1752    function entry_ping_count($entry_id) {
1753        if (isset($this->_ping_count_cache[$entry_id])) {
1754            return $this->_ping_count_cache[$entry_id];
1755        }
1756        $count = $this->get_var("
1757            select count(*)
1758              from mt_trackback, mt_tbping
1759             where trackback_entry_id = " . intval($entry_id) . "
1760               and tbping_visible = 1
1761               and tbping_tb_id = trackback_id
1762        ");
1763        $this->_ping_count_cache[$entry_id] = $count;
1764        return $count;
1765    }
1766
1767    function category_ping_count($cat_id) {
1768        $count = $this->get_var("
1769            select count(*)
1770              from mt_trackback, mt_tbping
1771             where trackback_category_id = " . intval($cat_id) . "
1772               and tbping_visible = 1
1773               and tbping_tb_id = trackback_id
1774        ");
1775        return $count;
1776    }
1777
1778    function &fetch_pings($args) {
1779        $entry_id = $args['entry_id'];
1780        # load pings 
1781        $sql = $this->include_exclude_blogs($args);
1782        if ($sql != '') {
1783            $blog_filter = 'and tbping_blog_id ' . $sql;
1784            if (isset($args['blog_id']))
1785                $blog =& $this->fetch_blog($args['blog_id']);
1786        } elseif ($args['blog_id']) {
1787            $blog =& $this->fetch_blog($args['blog_id']);
1788            $blog_filter = ' and tbping_blog_id = ' . $blog['blog_id'];
1789        }
1790        $order = isset($args['lastn']) ? 'desc' : 'asc';
1791        if (isset($args['sort_order'])) {
1792            if ($args['sort_order'] == 'descend') {
1793                $order = 'desc';
1794            } elseif ($args['sort_order'] == 'ascend') {
1795                $order = 'asc';
1796            }
1797        }
1798        if ($entry_id)
1799            $entry_filter = 'and trackback_entry_id = ' . intval($entry_id);
1800        $sql = "
1801            select mt_trackback.*, mt_tbping.*, mt_entry.entry_class
1802              from mt_trackback, mt_tbping, mt_entry
1803             where tbping_tb_id = trackback_id
1804             and trackback_entry_id = entry_id
1805               $entry_filter
1806               $blog_filter
1807               and tbping_visible = 1
1808             order by tbping_created_on $order
1809                   <LIMIT>";
1810        $sql = $this->apply_limit_sql($sql, $args['lastn'], $args['offset']);
1811        $pings = $this->get_results($sql, ARRAY_A);
1812        return $pings;
1813    }
1814
1815    function cache_categories(&$entry_list) {
1816        $id_list = '';
1817        foreach ($entry_list as $entry_id) {
1818            if (!isset($this->_cat_id_cache['e'.$entry_id])) {
1819                $id_list .= ','.$entry_id;
1820            }
1821        }
1822        $id_list = substr($id_list, 1);
1823        if (!$id_list)
1824            return;
1825        $query = "
1826            select *
1827              from mt_category, mt_placement
1828             where placement_entry_id in ($id_list)
1829               and placement_category_id = category_id
1830               and placement_is_primary = 1
1831        ";
1832        $results = $this->get_results($query, ARRAY_A);
1833        foreach ($entry_list as $entry_id) {
1834            $this->_cat_id_cache['e'.$entry_id] = null;
1835        }
1836        if (is_array($results)) {
1837            foreach ($results as $row) {
1838                $entry_id = $row['placement_entry_id'];
1839                $this->_cat_id_cache['e'.$entry_id] = $row;
1840                $cat_id = $row['category_id'];
1841                $this->_cat_id_cache['c'.$cat_id] = $row;
1842            }
1843        }
1844    }
1845
1846    function &fetch_category($cat_id) {
1847        if (isset($this->_cat_id_cache['c'.$cat_id])) {
1848            return $this->_cat_id_cache['c'.$cat_id];
1849        }
1850        $cats =& $this->fetch_categories(array('category_id' => $cat_id, 'show_empty' => 1));
1851        if ($cats && (count($cats) > 0)) {
1852            $this->_cat_id_cache['c'.$cat_id] = $cats[0];
1853            return $cats[0];
1854        } else {
1855            return null;
1856        }
1857    }
1858
1859    function &fetch_blog($blog_id) {
1860        if (isset($this->_blog_id_cache[$blog_id])) {
1861            return $this->_blog_id_cache[$blog_id];
1862        }
1863        list($blog) = $this->load('blog', $blog_id);
1864        $this->_blog_id_cache[$blog_id] = $blog;
1865        return $blog;
1866    }
1867
1868    function &get_archive_list($args) {
1869        $blog_id = $args['blog_id'];
1870        $at = $args['archive_type'];
1871
1872        $group_sql = $this->archive_list_sql($args);
1873        $results = $this->get_results($group_sql, ARRAY_N);
1874        if (is_array($results)) {
1875            if ($at == 'Daily') {
1876                $hi = sprintf("%04d%02d%02d", $results[0][1], $results[0][2], $results[0][3]);
1877                $low = sprintf("%04d%02d%02d", $results[count($results)-1][1], $results[count($results)-1][2], $results[count($results)-1][3]);
1878            } elseif ($at == 'Weekly') {
1879                require_once("MTUtil.php");
1880                $week_yr = substr($results[0][1], 0, 4);
1881                $week_num = substr($results[0][1], 4);
1882                list($y,$m,$d) = week2ymd($week_yr, $week_num);
1883                $hi = sprintf("%04d%02d%02d", $y, $m, $d);
1884                $week_yr = substr($results[count($results)-1][1], 0, 4);
1885                $week_num = substr($results[count($results)-1][1], 4);
1886                list($y,$m,$d) = week2ymd($week_yr, $week_num);
1887                $low = sprintf("%04d%02d%02d", $y, $m, $d);
1888            } elseif ($at == 'Monthly') {
1889                $hi = sprintf("%04d%02d32", $results[0][1], $results[0][2]);
1890                $low = sprintf("%04d%02d00", $results[count($results)-1][1], $results[count($results)-1][2]);
1891            } elseif ($at == 'Yearly') {
1892                $hi = sprintf("%04d0000", $results[0][1]);
1893                $low = sprintf("%04d0000", $results[count($results)-1][1]);
1894            } elseif ($at == 'Individual') {
1895                $hi = $results[0][1];
1896                $low = $results[count($results)-1][1];
1897            }
1898            $range = "'$low' and '$hi'";
1899            $link_cache_sql = "
1900                select fileinfo_startdate, fileinfo_url, blog_site_url, blog_file_extension
1901                  from mt_fileinfo, mt_templatemap, mt_blog
1902                 where fileinfo_startdate between $range
1903                   and fileinfo_archive_type = '$at'
1904                   and blog_id = $blog_id
1905                   and fileinfo_blog_id = blog_id
1906                   and templatemap_id = fileinfo_templatemap_id
1907                   and templatemap_is_preferred = 1
1908            ";
1909            $cache_results = $this->get_results($link_cache_sql, ARRAY_N);
1910            if (is_array($cache_results)) {
1911                foreach ($cache_results as $row) {
1912                    $date = $this->db2ts($row[0]);
1913                    $blog_url = $row[2];
1914                    $blog_url = preg_replace('!(https?://(?:[^/]+))/.*!', '$1', $blog_url);
1915                    $url = $blog_url . $row[1];
1916                    $url = _strip_index($url, array('blog_file_extension' => $row[3]));
1917                    $this->_archive_link_cache[$date.';'.$at] = $url;
1918                }
1919            }
1920        }
1921        return $results;
1922    }
1923
1924    function asset_count($args) {
1925        if (isset($args['blog_id'])) {
1926            $blog_filter = 'and asset_blog_id = '.intval($args['blog_id']);
1927        }
1928
1929        # Adds a type filter
1930        if (isset($args['type'])) {
1931            $type_filter = "and asset_class ='" . $args['type'] . "'";
1932        }
1933
1934        $count = $this->get_var("
1935            select count(*)
1936              from mt_asset
1937             where
1938                   1 = 1
1939                   $blog_filter
1940                   $type_filter
1941        ");
1942        return $count;
1943    }
1944
1945    function fetch_assets($args) {
1946        # load assets
1947
1948        if (isset($args['blog_id'])) {
1949            $blog_filter = 'and asset_blog_id = '.intval($args['blog_id']);
1950        }
1951
1952        # Adds a thumbnail filter to the filters list.
1953        if(isset($args['exclude_thumb']) && $args['exclude_thumb']) {
1954           $thumb_filter = ' and asset_parent is null'; 
1955        }
1956       
1957        # Adds a tag filter to the filters list.
1958        if (isset($args['tags']) or isset($args['tag'])) {
1959            $tag_arg = isset($args['tag']) ? $args['tag'] : $args['tags'];
1960            require_once("MTUtil.php");
1961            if (!preg_match('/\b(AND|OR|NOT)\b|\(|\)/i', $tag_arg)) {
1962                $not_clause = false;
1963            } else {
1964                $not_clause = preg_match('/\bNOT\b/i', $tag_arg);
1965            }
1966
1967            require_once("MTUtil.php");
1968            $include_private = 0;
1969            $tag_array = tag_split($tag_arg);
1970            foreach ($tag_array as $tag) {
1971                if ($tag && (substr($tag,0,1) == '@')) {
1972                    $include_private = 1;
1973                }
1974            }
1975
1976            $tags =& $this->fetch_asset_tags(array('blog_id' => $blog_id, 'tag' => $tag_arg, 'include_private' => $include_private));
1977            if (!is_array($tags)) $tags = array();
1978            $cexpr = create_tag_expr_function($tag_arg, $tags, 'asset');
1979
1980            if ($cexpr) {
1981                $tmap = array();
1982                $tag_list = array();
1983                foreach ($tags as $tag) {
1984                    $tag_list[] = $tag['tag_id'];
1985                }
1986                $ot =& $this->fetch_objecttags(array('tag_id' => $tag_list, 'datasource' => 'asset'));
1987                if ($ot) {
1988                    foreach ($ot as $o) {
1989                        $tmap[$o['objecttag_object_id']][$o['objecttag_tag_id']]++;
1990                        if (!$not_clause)
1991                            $asset_list[$o['objecttag_object_id']] = 1;
1992                    }
1993                }
1994                $ctx['t'] =& $tmap;
1995                $filters[] = $cexpr;
1996            } else {
1997                return null;
1998            }
1999        }
2000
2001        # Adds an author filter
2002        if (isset($args['author'])) {
2003            $author_filter = 'and author_name = \''.$this->escape($args['author']) . "'";
2004            $author_join = ', mt_author.*';
2005            $author_join_tbl = ', mt_author';
2006        }
2007
2008        # Adds an entry filter
2009        if (isset($args['entry_id'])) {
2010            $entry_filter = 'and (objectasset_object_ds = \'entry\' and objectasset_object_id = \'' . $this->escape($args['entry_id']) . '\' and asset_id = objectasset_asset_id)';
2011            $entry_join = ', mt_objectasset.*';
2012            $entry_join_tbl = ', mt_objectasset';
2013        }
2014
2015        # Adds an ID filter
2016        if (isset($args['id']))
2017            $id_filter = 'and asset_id = '.$args['id'];
2018
2019        # Adds a days filter
2020        if (isset($args['days'])) {
2021            $day_filter = 'and ' . $this->limit_by_day_sql('asset_created_on', intval($args['days']));
2022        }
2023
2024        # Adds a type filter
2025        if (isset($args['type'])) {
2026            $type_filter = "and asset_class ='" . $args['type'] . "'";
2027        }
2028
2029        # Adds a file extension filter
2030        if (isset($args['file_ext'])) {
2031            $ext_filter = "and asset_file_ext ='" . $args['file_ext'] . "'";
2032        }
2033
2034        # Addes sort order
2035        $order = 'desc';
2036        $sort_by = 'asset_created_on';
2037        if (isset($args['sort_order'])) {
2038            if ($args['sort_order'] == 'ascend')
2039                $order = 'asc';
2040            else if ($args['sort_order'] == 'descend')
2041                $order = 'desc';
2042        }
2043       
2044        if (isset($args['sort_by'])) {
2045            if ('score' != $args['sort_by']) {
2046                $sort_by = 'asset_' . $args['sort_by'];
2047            }
2048        }
2049
2050        # Build SQL
2051        $sql = "
2052            select mt_asset.* $author_join $entry_join
2053            from mt_asset $author_join_tbl $entry_join_tbl
2054            where
2055                1 = 1
2056                $id_filter
2057                $blog_filter
2058                $author_filter
2059                $entry_filter
2060                $day_filter
2061                $type_filter
2062                $ext_filter
2063                $thumb_filter
2064            order by
2065                $sort_by $order
2066                <LIMIT>
2067        ";
2068
2069        # Added Limit and offset
2070        $sql = $this->apply_limit_sql($sql, $args['lastn'], $args['offset']);
2071
2072        # Fetch resultset
2073        $result = $this->query_start($sql);
2074        if (!$result) return null;
2075        $assets = array();
2076        while (true) {
2077            $e = $this->query_fetch(ARRAY_A);
2078            if (!isset($e)) break;
2079            if (count($filters)) {
2080                foreach ($filters as $f) {
2081                    if (!$f($e, $ctx)) continue 2;
2082                }
2083            }
2084            $e = $this->expand_meta($e);
2085            $assets[] = $e;
2086        }
2087
2088        if (isset($args['sort_by']) && ('score' == $args['sort_by'])) {
2089            $assets_tmp = array();
2090            foreach ($assets as $a) {
2091                $assets_tmp[$a['asset_id']] = $a;
2092            }
2093            $scores = $this->fetch_sum_scores($args['namespace'], 'asset', $order,
2094                $id_filter . "\n" .
2095                $blog_filter . "\n" .
2096                $author_filter . "\n" .
2097                $day_filter . "\n" .
2098                $type_filter . "\n" .
2099                $ext_filter . "\n" .
2100                $thumb_filter . "\n"
2101            );
2102            $assets_sorted = array();
2103            foreach($scores as $score) {
2104                if (array_key_exists($score['objectscore_object_id'], $assets_tmp)) {
2105                    array_push($assets_sorted, $assets_tmp[$score['objectscore_object_id']]);
2106                    unset($assets_tmp[$score['objectscore_object_id']]);
2107                }
2108            }
2109            foreach ($assets_tmp as $et) {
2110                array_push($assets_sorted, $et);
2111            }
2112            $assets = $assets_sorted;
2113
2114        }
2115        return $assets;
2116    }
2117
2118    function archive_list_sql($args) {
2119        $blog_id = $args['blog_id'];
2120        $at = $args['archive_type'];
2121        $order = $args['sort_order'] == 'ascend' ? 'asc' : 'desc';
2122
2123        $year_ext = $this->apply_extract_date('year', 'entry_authored_on');
2124        $month_ext = $this->apply_extract_date('month', 'entry_authored_on');
2125        $day_ext = $this->apply_extract_date('day', 'entry_authored_on');
2126        if ($at == 'Daily') {
2127            $sql = "
2128                select count(*),
2129                       $year_ext as y,
2130                       $month_ext as m,
2131                       $day_ext as d
2132                  from mt_entry
2133                 where entry_blog_id = $blog_id
2134                   and entry_status = 2
2135                   and entry_class = 'entry'
2136                 group by
2137                       $year_ext,
2138                       $month_ext,
2139                       $day_ext
2140                 order by
2141                       $year_ext $order,
2142                       $month_ext $order,
2143                       $day_ext $order
2144                       <LIMIT>";
2145        } elseif ($at == 'Weekly') {
2146            $sql = "
2147                select count(*),
2148                       entry_week_number
2149                  from mt_entry
2150                 where entry_blog_id = $blog_id
2151                   and entry_status = 2
2152                   and entry_class = 'entry'
2153                 group by entry_week_number
2154                 order by entry_week_number $order
2155                       <LIMIT>";
2156        } elseif ($at == 'Monthly') {
2157            $sql = "
2158                select count(*),
2159                       $year_ext as y,
2160                       $month_ext as m
2161                  from mt_entry
2162                 where entry_blog_id = $blog_id
2163                   and entry_status = 2
2164                   and entry_class = 'entry'
2165                 group by
2166                       $year_ext,
2167                       $month_ext
2168                 order by
2169                       $year_ext $order,
2170                       $month_ext $order
2171                       <LIMIT>";
2172        } elseif ($at == 'Yearly') {
2173            $sql = "
2174                select count(*),
2175                       $year_ext as y
2176                  from mt_entry
2177                 where entry_blog_id = $blog_id
2178                   and entry_status = 2
2179                   and entry_class = 'entry'
2180                 group by
2181                       $year_ext
2182                 order by
2183                       $year_ext $order
2184                       <LIMIT>";
2185        } elseif ($at == 'Individual') {
2186            $sql = "
2187                select entry_id,
2188                       entry_authored_on
2189                  from mt_entry
2190                 where entry_blog_id = $blog_id
2191                   and entry_status = 2
2192                   and entry_class = 'entry'
2193                 order by entry_authored_on $order
2194                       <LIMIT>";
2195        }
2196        $sql = $this->apply_limit_sql($sql, $args['lastn'], $args['offset']);
2197        return $sql;
2198    }
2199
2200    function db2ts($dbts) {
2201        $dbts = preg_replace('/[^0-9]/', '', $dbts);
2202        return $dbts;
2203    }
2204
2205    function ts2db($ts) {
2206        preg_match('/^(\d\d\d\d)?(\d\d)?(\d\d)?(\d\d)?(\d\d)?(\d\d)?$/', $ts, $matches);
2207        list($all, $y, $mo, $d, $h, $m, $s) = $matches;
2208        return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $y, $mo, $d, $h, $m, $s);
2209    }
2210
2211    function get_results($query = null, $output = ARRAY_A) {
2212        $rows = parent::get_results($query, $output);
2213        if (is_array($rows)) {
2214            $rows = array_map(array($this,"convert_fieldname"), $rows);
2215        }
2216        return $this->expand_meta($rows);
2217    }
2218
2219    function &convert_fieldname($array) {
2220        return $array;
2221    }
2222
2223    function expand_meta($rows) {
2224        $expanded = array();
2225        if (is_array($rows)) {
2226            foreach ($rows as $key => $value) {
2227                if (is_array($value)) {
2228                    $expanded[$key] = $this->expand_meta($value);
2229                } else {
2230                    if (preg_match('/(\w+)_meta$/', $key, $prefix)) {
2231                        $data = $this->unserialize($value);
2232                        if (isset($data)) {
2233                            foreach ($data as $k => $v) {
2234                                $expanded[$prefix[1] . '_' . $k] = $v;
2235                            }
2236                        }
2237                    } else {
2238                        $expanded[$key] = $value;
2239                    }
2240                }
2241            }
2242        }
2243        return $expanded;
2244</