* Jerome Lavigne * * $Id$ ******************************************************************************/ define('LP_CONTEXT_INDEX', 1); define('LP_CONTEXT_CATEGORY', 2); define('LP_CONTEXT_ARCHIVES', 4); define('LP_CONTEXT_POST', 8); define('LP_CONTEXT_STATIC', 16); define('LP_CONTEXT_SEARCH', 32); define('LP_CONTEXT_AUTHOR', 64); define('LP_CONTEXT_TAG', 128); define('LP_CONTEXT_ALL', LP_CONTEXT_INDEX | LP_CONTEXT_CATEGORY | LP_CONTEXT_ARCHIVES | LP_CONTEXT_POST | LP_CONTEXT_STATIC | LP_CONTEXT_SEARCH | LP_CONTEXT_AUTHOR | LP_CONTEXT_TAG); // maybe move the following to a (class) method, when (if) we add user-defined contexts define('LP_CONTEXTS', 'index category archives post static search author tag'); class Frontend { var $_hooks = array( 'get_posts', 'get_posts_loop', 'insert_comment', 'start_render', 'sidebar', 'parse_post', 'parse_comment', 'pre_render', 'post_render', 'shutdown'); // set in constructor var $options; var $raw_urls = false; var $db; var $cache; var $tpl; var $messages; var $tables_prefix; var $tables; var $title; var $where_date; var $templates = array( 'index' => 'index.xml', 'header' => 'header.xml', 'sidebar' => 'sidebar.xml', 'footer' => 'footer.xml'); var $_plugins = array(); var $_plugin_dir = array(); // getCategories var $_categories; // getCatGroups var $_catgroups; // getArchives var $_archives; // getContext var $context; // checkCategory var $_category_nicenames; // getPosts var $_posts; var $num_posts; var $_post_date; // cleared in getPosts, set in renderPost var $posts_join; var $posts_where; var $posts_in; // getPages var $_pages; // getPostTags var $_posttags; // getTags var $_tags; // startRender var $_templates_set; // renderPost var $current_post; // parsing helpers var $_block_post; var $_sidebar; // getMailHelper var $_mail_helper; // getSpamChecker var $_spam_checker; // extractKeywords; var $search_keywords; // base messages, merged with the ones from the localized file var $_base_messages = array( 'no_posts' => 'No post found', 'comments_open_nocomments' => 'Be the first to add a comment to this article.', 'comments_closed_nocomments' => 'Comments closed.', 'comments_closed' => 'Comments closed.', 'categories_header' => 'Categories', 'comment_accepted' => 'Comment posted.', 'comment_required_fields' => 'Please fill in all required fields', 'comment_form_message' => "Your email address is required but won't be displayed.", 'comment_mail_subject' => 'New comment', 'post_mail_subject' => 'Reading suggestion', 'mail_sent' => 'Message sent.', 'post_continued' => 'continued...', 'search_title' => 'Search Results', 'comment' => 'comment', 'comments' => 'comments', 'post' => 'post', 'posts' => 'posts', 'thereis' => 'There is', 'thereare' => 'There are' ); function Frontend(&$db_options, &$options, $cache=false, $view_type='html') { $this->cache =& $cache; $this->view_type = $view_type; /********************************************************************** * table names **********************************************************************/ if (!isset($db_options['prefix'])) $this->raiseError('missing tables prefix in config.php', 'Frontend', __LINE__, E_USER_ERROR); $this->tables_prefix = $dbt = $db_options['prefix']; $this->tables = array(); foreach (array('options', 'categories', 'posts', 'post2cat', 'comments', 'users', 'postmeta', 'links', 'linkcategories', 'stats', 'tags') as $k) $this->tables[$k] = "${dbt}_$k"; /********************************************************************** * options **********************************************************************/ if (!isset($options) || !is_array($options) || (count($options) == 0)) { // connection is delayed if you use fs-based options to speed up fs-based caches $this->_connect($db_options); // retrieve from db $this->db->query("select option_name, option_value from " . $this->tables['options'] . " where option_name like 'lp_opt_%' or option_name='gmt_offset'"); foreach ($this->db->all() as $row) $options[substr($row['option_name'], 7)] = $row['option_value']; if (count($options) == 0) $this->raiseError('lightpress options not set in database', 'Frontend', __LINE__, E_USER_ERROR); // sanitize if (isset($options['posts_per_page'])) $options['posts_per_page'] = (int)$options['posts_per_page']; if (isset($options['posts_per_rss'])) $options['posts_per_rss'] = (int)$options['posts_per_rss']; if (isset($options['plugins']) && is_string($options['plugins']) && !empty($options['plugins'])) $options['plugins'] = unserialize($options['plugins']); if (isset($options['set'])) { // ugly but using a separate query or checking every option name would be a waste $options['gmt_offset'] = (int)$options['set'] * 3600; unset($options['set']); } // add plugins if none are set if (!isset($options['plugins']) || empty($options['plugins'])) { $options['plugins'] = $this->getDefaultPlugins(); } } $options['wpff_revision'] = substr(substr('$Revision$', 11), 0, -2); $options['wpff_version'] = $this->getVersion(); $options = array_merge($this->getBaseOptions(), $options); $this->options =& $options; // set basedir (we cannot set it in config.php anymore since it may have been defined in the db) if (DIRECTORY_SEPARATOR == '/') ini_set('include_path', ini_get('include_path') . ':' . $options['basedir']); else ini_set('include_path', ini_get('include_path') . ';' . $options['basedir']); foreach($this->getCriticalOptions() as $option_name) { if (!isset($options[$option_name])) die("Cannot start LightPress Frontend: missing option '$option_name' in configuration file."); } // set base options for those that could not be easily assigned in _base_options if (!isset($options['wp_url'])) $options['wp_url'] = $options['url']; // default installation is to replace WP // guess URL for templates - templates dir should either be in site root or in the WP's lightpress plugin dir // TODO: make this work for non-standard configs (or should users just ignore this var in such a case?) if (strstr(strtolower($options['basedir']), 'wp-content')) $options['template_url'] = $options['wp_url'] . '/wp-content/plugins/lightpress/templates'; else $options['template_url'] = $options['url'] . '/templates'; /********************************************************************** * permalink stuff **********************************************************************/ if (empty($options['post_prefix'])) { $this->raw_urls = true; } else { if (!isset($options['post_permalink_struct'])) $options['post_permalink_struct'] = $this->prefixToPermalinkStruct($options['post_prefix']); if (!isset($options['archives_permalink_struct'])) $options['archives_permalink_struct'] = $this->prefixToPermalinkStruct($options['archives_prefix']); } /********************************************************************** * db instance **********************************************************************/ $this->_connect($db_options); require_once 'classes/DBlite/MySQL.php'; $this->db =& new DBlite_MySQL($db_options); /********************************************************************** * set needed attributes **********************************************************************/ $this->where_date = gmdate("Y-m-d H:i:s"); $this->title = $options['blogname']; /********************************************************************** * localized messages **********************************************************************/ $config_messages_file = implode( DIRECTORY_SEPARATOR, array($options['basedir'], 'lang', $options['lang'] . '_' . $options['charset'] . '_messages.php')); if (is_readable($config_messages_file)) { require_once $config_messages_file; $config_messages = array_merge($this->_base_messages, $config_messages); $this->messages =& $config_messages; } else { // en_US UTF-8 defaults $this->messages =& $this->_base_messages; } /********************************************************************** * set context **********************************************************************/ $this->context =& $this->getContext(); /********************************************************************** * locale **********************************************************************/ // TODO: trap wrong locale name setlocale(LC_TIME, $options['lang'] . '.' . $options['charset']); /********************************************************************** * template instance **********************************************************************/ require_once 'classes/Template.php'; $this->tpl =& new Template(sprintf( '%s/templates/%s/%s.%s', $options['basedir'], $options['template'], $options['lang'], $options['charset'])); // set options as template variables $tpl_options = array(); foreach ($options as $k=>$v) { if (is_array($v)) continue; $tpl_options["option_$k"] = $v; } if (isset($options['plugin_names']) && is_array($options['plugin_names'])) { foreach ($options['plugin_names'] as $p) $tpl_options[$p] = ''; } $tpl_options['lp_context_type'] = $this->context['type']; $tpl_options['context_url'] = $this->context['url']; $tpl_options['page_self'] = $_SERVER['REQUEST_URI']; $this->tpl->setVar($tpl_options); unset($tpl_options); /********************************************************************** * sort out plugins **********************************************************************/ $this->_plugins =& $this->getPlugins($options['plugins'], $this->context['type']); } function _connect($db_options) { if (!is_null($this->db)) return; require_once 'classes/DBlite/MySQL.php'; $this->db =& new DBlite_MySQL($db_options); } function &getPlugins($plugins_map, $current_context, $hook=null) { $plugins = array(); if (is_null($hook)) { $hooks =& $this->_hooks; } else { $hooks = array($hook); } foreach ($hooks as $hook) $plugins[$hook] = array(); // assume that context constants have been declared in config.php as // LP_CONTEXT_$context_type $local_context = 'LP_CONTEXT_' . strtoupper($this->context['type']); $local_context = defined($local_context) ? constant($local_context) : LP_CONTEXT_INDEX; $this->local_context = $local_context; $hide_plugins = array(); foreach ($plugins_map as $plugin_name=>$plugin_details) { list($context_type, $plugin_args) = $plugin_details; $hideplugin = true; if ($context_type & $local_context) { if (@include_once("plugins/${plugin_name}.php")) { $plugin =& new $plugin_name($this, $plugin_args); if ($plugin->active) { foreach (array_intersect($hooks, $plugin->hooks) as $hook) { $plugins[$hook][] =& $plugin; } $this->_plugin_dir[strtolower(get_class($plugin))] =& $plugin; $hideplugin = false; } } else { // TODO: deal with missing plugins, log to a file? } } if ($hideplugin) $hide_plugins['PLUGIN_' . strtoupper($plugin_name)] = ''; } $this->tpl->setVar($hide_plugins); return $plugins; } function &getPlugin($plugin_name) { $plugin_name = strtolower($plugin_name); if (isset($this->_plugin_dir[$plugin_name])) return $this->_plugin_dir[$plugin_name]; return null; } function _processPlugins($hook, &$hook_data, $hide=false) { // render plugins $plugins =& $this->_plugins; if (isset($plugins[$hook])) { foreach ($plugins[$hook] as $k => $v) { if ($hide) $plugins[$hook][$k]->hide(); else $plugins[$hook][$k]->run($hook, $hook_data); } } } /*************************************************************************** * get data methods **************************************************************************/ function &getCategories($force=false) { /* * gets blog categories and builds the structures needed to parse * the menu, and posts * * if you call this method manually before the parse methods, the * structures are cached and reused later */ if (is_null($this->_categories) || $force) { $tables =& $this->tables; $q = " select p2c.category_id as cat_id, c1.category_parent as catgroup_id, cp.cat_name as catgroup, cp.category_nicename as catgroup_nicename, c1.cat_name, c1.category_nicename, c1.category_description, count(p2c.post_id) as numposts, count(c2.cat_id) as num_child, UNIX_TIMESTAMP(max(p.post_date_gmt)) + '" . $this->options['gmt_offset'] . "' as last_post_date, UNIX_TIMESTAMP(max(p.post_date_gmt)) as last_post_date_gmt from " . $tables['post2cat'] . " p2c inner join " . $tables['posts'] . " p on p2c.post_id=p.id inner join " . $tables['categories'] . " c1 on p2c.category_id = c1.cat_ID left join " . $tables['categories'] . " cp on c1.category_parent = cp.cat_ID left join " . $tables['categories'] . " c2 on c2.category_parent = p2c.category_id where p.post_status='publish' and p.post_date_gmt <= '" . $this->where_date . "' group by p2c.category_id, c1.category_parent, c1.cat_name, c1.category_nicename, cp.cat_name, cp.category_nicename order by catgroup, c1.cat_name"; $this->db->query($q); $categories = array(); $catgroups = array(); foreach ($this->db->all() as $category) { if ($this->raw_urls) { $category['category_permalink'] = 'index.php?c=' . $category['cat_id']; $category['catgroup_permalink'] = 'index.php?c=' . $category['catgroup_id']; } else { $category['catgroup_permalink'] = $this->options['category_prefix'] . '/' . $category['catgroup_nicename']; $category['category_permalink'] = $this->options['category_prefix'] . '/' . $category['category_nicename']; } $categories[$category['cat_id']] = $category; } $this->_categories =& $categories; } return $this->_categories; } function &getArchives($force=false) { /* * gets blog archives and builds the structure used later to parse * the sidebar * * if you call this method manually before the parse methods, the * structures are cached and reused later */ if (is_null($this->_archives) || $force) { $tables =& $this->tables; $q = "select year(post_date) as y, lpad(month(post_date), 2, '0') as m, count(*) as numposts from " . $tables['posts'] . " where post_status = 'publish' and post_date_gmt <= '" . $this->where_date . "' group by y, m order by y desc, m desc"; $result = $this->db->query($q); $archives = array(); $archive_label =& $this->options['archive_label']; $archive_prefix =& $this->options['archives_prefix']; // PHP tends to forget the locale setlocale(LC_TIME, $this->options['lang'] . '.' . $this->options['charset']); foreach ($this->db->all() as $m) { $month = (int)$m['m']; $m['month'] = $month; $archive_date = mktime(0, 0, 0, $month, 1, (int)$m['y']); $m['date'] = $archive_date; $m['label'] = strftime($archive_label, $archive_date); if ($this->raw_urls) $m['permalink'] = 'index.php?m=' . $m['y'] . $m['m']; else $m['permalink'] = strftime($this->options['archives_permalink_struct'], $archive_date); $date = $m['y'] . sprintf("%02d", $month); $archives[$date] = $m; } $this->_archives =& $archives; } return $this->_archives; } function &getContext($context_type=null, $context_filter=null, $context_index=0, $context_reqtype='') { /* * context type is post/category/archives/static/search/author, etc. * context filter is the key used to retrieve the main object (eg post name) * context index is the starting index when displaying lists of objects * context reqtype is used to distinguish all-purpose plugins from specialized (eg html/feed plugins) * */ $tables =& $this->tables; $options =& $this->options; $context_url = ''; $context_label = ''; $context_hierarchy = array(); $context_f = $context_g = $context_w = ''; // query vars $context_j = " RIGHT JOIN " . $tables['users'] . " u on p.post_author=u.id "; /*************************************************************************** * context type and filter **************************************************************************/ if (is_null($context_type) || is_null($context_filter)) { $requestvars = array( 'p'=>'post', 'pi'=>'post_id', 'c'=>'category', 'a'=>'archives', // LP vars 's'=>'static', 'q'=>'search', 'u' =>'author', 'y'=>'archives', 'tag'=>'tag',// LP vars 'm'=>'archives', 'postname'=>'post', 'category_name'=>'category', // old WP vars 'pagename'=>'static', 'year'=>'archives'); // old WP vars foreach ($requestvars as $k=>$v) { if (isset($_REQUEST[$k]) && !empty($_REQUEST[$k])) { $context_type = $v; $context_filter = strip_tags($_REQUEST[$k]); break; } } /*************************************************************************** * nested contexts **************************************************************************/ if (empty($context_type) && isset($_GET['y1'])) { $y1 = strip_tags($_GET['y1']); $y2 = (isset($_GET['y2']) ? strip_tags($_GET['y2']) : null); $y3 = (isset($_GET['y3']) ? strip_tags($_GET['y3']) : null); $parent = $subparent = $child = null; // try pages first $pages =& $this->getPages(); foreach ($pages as $k=>$v) { switch ($v['post_name']) { case $y1: $parent =& $pages[$k]; break; case $y2: $subparent =& $pages[$k]; break; case $y3: $child =& $pages[$k]; break; } } if ($child) { $context_type = 'static'; $context_filter = $child['post_name']; $context_url = $this->getPagePermalink( $child['id'], $child['post_name'], is_null($subparent) ? '' : $subparent['post_name'], is_null($parent) ? '' : $parent['post_name']); } else if ($subparent) { $context_type = 'static'; $context_filter = $subparent['post_name']; $context_url = $this->getPagePermalink( $subparent['id'], $subparent['post_name'], is_null($parent) ? '' : $parent['post_name'], ''); } else if ($parent) { $context_type = 'static'; $context_filter = $parent['post_name']; $context_url = $this->getPagePermalink( $parent['id'], $parent['post_name'], '', ''); } else { // try categories $categories =& $this->getCategories(); foreach ($categories as $k=>$v) { switch ($v['category_nicename']) { case rawurlencode($y1): $parent =& $categories[$k]; break; case rawurlencode($y2): $subparent =& $categories[$k]; break; case rawurlencode($y3): $child =& $categories[$k]; break; } } if ($child) { $context_type = 'category'; $context_filter = $child['cat_id']; } else if ($subparent) { $context_type = 'category'; $context_filter = $subparent['cat_id']; } else if ($parent) { $context_type = 'category'; $context_filter = $parent['cat_id']; } else { // TODO: output a customized error page } } // we might as well store the hierarchy, might be useful to plugins $context_hierarchy = array(&$parent, &$subparent, &$child); } if (ini_get('magic_quotes_gpc') == 1) $context_filter = stripslashes($context_filter); } /*************************************************************************** * context index **************************************************************************/ if ($context_index == 0) { if (isset($_REQUEST['i']) && !empty($_REQUEST['i'])) $context_index = (int)$_REQUEST['i']; else if (isset($_REQUEST['paged']) && !empty($_REQUEST['paged'])) $context_index = (int)$_REQUEST['paged'] * (int)$this->options['posts_per_page']; } /*************************************************************************** * reqtype **************************************************************************/ if (empty($this->_reqtype) && isset($_GET['reqtype'])) $context_reqtype = $_GET['reqtype']; /*************************************************************************** * fix/check filter/url and set queryvars **************************************************************************/ switch ($context_type) { case 'post': if ($this->raw_urls) { // use WP-style post permalink, e.g. index.php?p=id $context_w = "AND (p.post_status='publish') AND p.id='$context_filter'"; } else { $context_w = "AND (p.post_status='publish') AND p.post_name='$context_filter'"; } // delay setting up context_url $context_url = null; break; case 'post_id': $context_type = 'post'; $context_w = "AND (p.post_status='publish') AND p.id='$context_filter'"; // delay setting up context_url $context_url = null; break; case 'category': // we avoid a join in the posts query, and swap the shortname // so as to be able to access categories by index // a second loop since the index page is accessed more $categories =& $this->getCategories(); $found = false; if (!isset($categories[$context_filter])) { // WP encodes the shortname in the DB, ugh! $nicename = rawurlencode($context_filter); foreach ($categories as $cat_id => $category) { if ($category['category_nicename'] == $nicename) { $context_filter = $cat_id; $context_label = $category['cat_name']; $this->title .= " » " . $category['cat_name']; $found = true; break; } } } else { $found = true; $context_label = $categories[$context_filter]['cat_name']; $this->title .= " » " . $categories[$context_filter]['cat_name']; } if (!$found) { $context_type = 'post'; $context_w = "AND (p.post_status='publish') AND p.id=''"; } else { $context_url = $categories[$context_filter]['category_permalink']; $context_j .= " INNER JOIN " . $tables['post2cat'] . " p2c on p.id=p2c.post_id "; $context_w = "AND (p.post_status='publish') AND p2c.category_id='$context_filter'"; } break; case 'archives': if (!$this->raw_urls) { // fix context_filter if we have a 'y' or 'year' var if (isset($_REQUEST['y']) && isset($_REQUEST['m'])) { $context_filter .= strip_tags($_REQUEST['m']); } elseif (isset($_REQUEST['year']) && isset($_REQUEST['monthnum'])) { $context_filter .= strip_tags($_REQUEST['monthnum']); } } $archives =& $this->getArchives(); if (!in_array($context_filter, array_keys($archives))) { $context_type = 'post'; $context_w = "AND (p.post_status='publish') AND p.id=''"; } else { $archive =& $archives[$context_filter]; $this->title .= " » " . $archive['label']; $context_label = $archive['label']; $context_url = $archive['permalink']; $context_w = "AND (p.post_status='publish') AND year(p.post_date)=" . $archive['y'] . " AND month(p.post_date)=" . $archive['m'] . " "; } break; case 'static': $context_w = "AND (p.post_status='static') AND p.post_name='$context_filter'"; $context_j .= ' LEFT JOIN ' . $tables['posts'] . ' AS parent ON p.post_parent = parent.ID '; $context_f = ', parent.post_name AS parent_name '; // delay setting up context_url as we do not have the id yet $context_url = null; break; case 'search': $this->title .= " » " . $this->messages['search_title']; $kw =& $this->_extractKeywords($context_filter); if (count($kw) > 0) { $context_j .= " LEFT JOIN {$tables['tags']} AS tags ON (p.ID = tags.post_id) "; $context_w .= " AND (p.post_status='publish' OR p.post_status='static') AND ("; $context_w .= "(p.post_title LIKE '%" . implode("%' AND p.post_title LIKE '%", $kw) . "%')"; $context_w .= " OR "; $context_w .= "(p.post_content LIKE '%" . implode("%' AND p.post_content LIKE '%", $kw) . "%')"; $context_w .= " OR "; $context_w .= "(tags.tag_name='" . implode("' OR tags.tag_name='", $kw) . "')"; $context_w .= ") "; } if ($this->raw_urls) $context_url = 'index.php?q=' . urlencode($context_filter); else $context_url = $options['search_prefix'] . '/' . urlencode($context_filter); break; case 'author': $this->title .= ' » ' . $context_filter; $context_w = "AND (p.post_status='publish') AND u.user_nickname='$context_filter'"; if ($this->raw_urls) $context_url = 'index.php?u=' . urlencode($context_filter); else $context_url = $options['author_prefix'] . '/' . urlencode($context_filter); break; case 'tag': $this->title .= ' » ' . $context_filter; $context_url = $this->getTagPermalink($context_filter); $context_j .= " LEFT JOIN {$tables['tags']} AS tags ON (p.ID = tags.post_id) "; $context_w = " AND (p.post_status='publish' OR p.post_status='static') AND (tags.tag_name='" . addslashes($context_filter) . "') "; break; default: $context_w = "AND (p.post_status='publish')"; break; } if (!is_null($context_url)) $context_url = $options['url'] . (($context_url != '') ? '/' : '') . $context_url; $context = array( 'type' => $context_type, 'filter' => $context_filter, 'hierarchy' => $context_hierarchy, 'index' => $context_index, 'url' => $context_url, 'label' => $context_label, 'reqtype' => $context_reqtype, 'queryvars' => array('f'=>$context_f, 'j'=>$context_j, 'w'=>$context_w, 'g'=>$context_g)); return $context; } function getLastModified($check_comments=false) { $db =& $this->db; $tables =& $this->tables; list($qv_f, $qv_j, $qv_w, $qv_g) = array_values($this->context['queryvars']); $field = "post_modified_gmt"; if ($check_comments) { $field = "comment_date_gmt"; $qv_j .= " RIGHT JOIN " . $tables['comments'] . " c ON c.comment_post_id=p.id "; } $q = "SELECT UNIX_TIMESTAMP(MAX($field)) as tstamp, MAX($field) as lastmoddate FROM {$tables['posts']} p $qv_j WHERE p.post_date_gmt <= '{$this->where_date}' $qv_w"; $db->query($q); $row = $db->next(); if ($row == null || !isset($row['tstamp'])) // no timestamp, generate one and subtract gmt_offset return time() - $this->options['gmt_offset']; else return (int)$row['tstamp']; // GMT timestamp } function &getPosts($context_type=null, $context_filter=null, $start_record=null, $num_records=null, $force=false, $simple=false) { $context = null; // TODO: fix the following if ((!is_null($context_type) && $context_type != $this->context['type']) || (!is_null($context_filter) && $context_filter != $this->context['filter'])) $context =& $this->getContext($context_type, $context_filter); if (is_null($context)) { // check if we can return the cached result if (!is_null($this->_posts) && !$force) return $this->_posts; else $context =& $this->context; } $context_type =& $context['type']; $context_filter =& $context['filter']; $options =& $this->options; $tables =& $this->tables; // render plugins $this->_processPlugins('get_posts', $context['queryvars']); list($f, $j, $w, $g) = array_values($context['queryvars']); if (is_null($num_records)) $num_records = $options['posts_per_page']; if (is_null($start_record)) $start_record = $context['index']; $set_title = (($context_type == 'post') || ($context_type == 'static')); /******************************************************************* * create the context-dependent query ******************************************************************/ if ($context_type == 'post' || $context_type == 'static') // save the count(*) query $num_records = 1; /******************************************************************* * retrieve posts ******************************************************************/ $q = "SELECT p.id as post_id, p.post_author as post_author_id, UNIX_TIMESTAMP(p.post_date_gmt) + '" . $this->options['gmt_offset'] . "' as post_tstamp, UNIX_TIMESTAMP(p.post_date_gmt) as post_tstamp_gmt, p.post_title, p.post_content, p.post_status, p.comment_status, p.ping_status, p.post_name, p.guid as post_guid, u.user_nickname as post_author, u.user_login as post_author_login $f FROM " . $tables['posts'] . " p $j WHERE p.post_date_gmt <= '" . $this->where_date . "' $w GROUP BY p.id, p.post_author, post_tstamp, post_tstamp_gmt, p.post_title, p.post_content, p.post_status, p.comment_status, p.ping_status, p.post_name, u.user_nickname, u.user_login $g ORDER BY p.post_date DESC " . ($num_records > 0 ? "LIMIT $start_record, $num_records" : ""); $this->db->query($q); $posts = $this->db->all(); /******************************************************************* * store posts count ******************************************************************/ $num_posts = $this->db->count; // used also in the posts loop below switch ($num_records) { case 0: case 1: $this->num_posts = $num_posts; if (is_null($this->context['url'])) { // might have been set when checking the hierarchy context $this->context['url'] = $options['url']; // no posts, set it to the index URL if (($num_records == 1) && isset($posts[0])) { if ($posts[0]['post_status'] == 'static') $this->context['url'] .= '/' . $this->getPagePermalink($posts[0]['post_id'], $posts[0]['post_name']); else $this->context['url'] .= '/' . $this->getPermalink($posts[0]['post_id'], $posts[0]['post_name'], $posts[0]['post_tstamp']); } } break; default: $q = "SELECT count(*) as num from " . $tables['posts'] . " p $j WHERE p.post_date_gmt <= '" . $this->where_date . "' $w"; $this->db->query($q); $this->num_posts = (int)$this->db->get('num'); } if ($num_posts == 0) return $posts; /******************************************************************* * create the where filter for later queries (e.g. categories and comments) ******************************************************************/ $posts_in = array(); foreach ($posts as $post) $posts_in[] = $post['post_id']; // store in context as well $this->posts_in = $posts_in = implode(',', $posts_in); if (!$simple) { /******************************************************************* * retrieve posts comments * (join/group by/having in the posts query does not work) ******************************************************************/ $q = "select comment_post_id as post_id, count(*) as num_comments " . "from " . $tables['comments'] . " " . "where comment_post_id in ($posts_in) and comment_approved = '1' " . "group by comment_post_id" ; $this->db->query($q); $posts_comments = array(); foreach ($this->db->all() as $post) $posts_comments[$post['post_id']] = $post['num_comments']; /******************************************************************* * retrieve posts categories ******************************************************************/ $q = "select distinct post_id, category_id from " . $tables['post2cat'] . " " . "where post_id in ($posts_in) order by post_id, category_id"; $this->db->query($q); $posts_categories = array(); foreach ($this->db->all() as $p2c) { $post_id = $p2c['post_id']; if (!isset($posts_categories[$post_id])) $posts_categories[$post_id] = array(); $posts_categories[$post_id][] = $p2c['category_id']; } /******************************************************************* * retrieve posts' tags ******************************************************************/ /* $q = "SELECT DISTINCT post_id, tag_name AS name FROM {$tables['tags']} tag WHERE post_id IN ({$this->posts_in}) ORDER BY post_id, name"; $this->db->query($q); $posts_tags = array(); foreach ($this->db->all() as $tag) { $post_id = $tag['post_id']; if (!isset($posts_tags[$post_id])) $posts_tags[$post_id] = array(); $posts_tags[$post_id][] = $tag['name']; } */ } /******************************************************************* * loop through posts and fill in missing attributes ******************************************************************/ $messages =& $this->messages; for ($i=0; $i<$num_posts;$i++) { $post =& $posts[$i]; $tstamp = (int)$post['post_tstamp']; $content = explode('', stripslashes($post['post_content']), 2); $post['post_content'] = $this->paragrapher($content[0]); $post['post_more'] = (count($content) > 1) ? '' . $this->paragrapher($content[1]) : ''; $post['post_title'] = stripslashes($post['post_title']); if ($set_title) $this->title .= ' » ' . $post['post_title']; $post['post_title_xmlsafe'] = htmlspecialchars($post['post_title'], ENT_QUOTES); $post['post_date'] = strftime($options['date_format'], $tstamp); $post['post_short_date'] = strftime($options['short_date_format'], $tstamp); $post['post_time'] = strftime($options['time_format'], $tstamp); $post['post_short_time'] = strftime($options['short_time_format'], $tstamp); $post['post_tstamp'] = $tstamp; if ($post['post_status'] == 'static') $post['post_permalink'] = $this->getPagePermalink($post['post_id'], $post['post_name']); else $post['post_permalink'] = $this->getPermalink($post['post_id'], $post['post_name'], $tstamp); $post['post_year'] = strftime("%Y", $tstamp); $post['post_month'] = strftime("%m", $tstamp); $post['post_day'] = strftime("%d", $tstamp); if (!$simple) { $post['post_comments'] = isset($posts_comments[$post['post_id']]) ? (int)$posts_comments[$post['post_id']] : 0; $post['post_comments_label'] = $post['post_comments'] == 1 ? $messages['comment'] : $messages['comments']; if ($context_type != 'static') $post['categories'] =& $posts_categories[$post['post_id']]; else $post['categories'] = array(); /* if (isset($posts_tags[ $post['post_id'] ])) $post['tags'] = $posts_tags[ $post['post_id'] ]; else $post['tags'] = array(); */ } $post['post_class_suffix'] = ($i == ($num_posts - 1)) ? '_last' : ''; // render plugins $this->_processPlugins('get_posts_loop', $post); } $this->_posts =& $posts; $this->_post_date = null; return $this->_posts; } function &getPages() { if (is_null($this->_pages)) { $q = "select p.id, p.post_name, p.post_title, p.post_parent, " . "UNIX_TIMESTAMP(p.post_date_gmt) + '" . $this->options['gmt_offset'] . "' as post_tstamp " . "from " . $this->tables['posts'] . " p " . "where p.post_status='static' and p.post_date_gmt <= '" . $this->where_date . "' " . "order by p.post_parent, p.post_title"; $this->db->query($q); $_pages =& $this->db->all(); $pages = array(); $deferred = array(); foreach ($_pages as $k=>$page) { $parent = $page['post_parent']; $_pages[$k]['root_page'] = empty($parent); $_pages[$k]['children'] = array(); if (!empty($parent)) { if (isset($pages[$parent])) $pages[$parent]['children'][$page['post_title']] =& $_pages[$k]; else $deferred[$page['id']] = array($page['post_title'], $parent); } $pages[$page['id']] =& $_pages[$k]; } foreach ($deferred as $id=>$details) { list($title, $parent) = $details; if (isset($pages[$parent])) { $pages[$parent]['children'][$title] =& $pages[$id]; } else $pages[$id]['parent'] = ''; } // we use the title as a key for children to ease sorting, // but we don't sort here to skip a second recursion that // as it may not be used in the current context $this->_pages =& $pages; } return $this->_pages; } function getPagePermalink($post_id, $post_name, $parent_name=null, $ancestor_name=null) { if ($this->raw_urls) return 'index.php?page_id=' . $post_id; $options =& $this->options; if (!empty($options['pages_prefix'])) return $options['pages_prefix'] . '/' . $post_name . $options['pages_suffix']; // build hierarchy if (is_null($parent_name) || is_null($ancestor_name)) { $pages =& $this->getPages(); if (!isset($pages[$post_id])) return; $tokens = array(); $id = $post_id; while (isset($pages[$id])) { $tokens[] = $pages[$id]['post_name']; $id = $pages[$id]['post_parent']; } $tokens = array_reverse($tokens); } else { $tokens = array(); if (!empty($ancestor_name)) $tokens[] = $ancestor_name; if (!empty($parent_name)) $tokens[] = $parent_name; $tokens[] = $post_name; } return implode('/', $tokens) . $options['pages_suffix']; } function getPermalink($post_id, $post_name, $post_tstamp) { $options =& $this->options; if ($this->raw_urls) return 'index.php?p=' . $post_id; return sprintf( strftime($this->options['post_permalink_struct'], $post_tstamp), $post_name, $post_id); } function &getComments($post_id=null, $limit=null) { $db =& $this->db; $q = "select *, UNIX_TIMESTAMP(comment_date_gmt) + '" . $this->options['gmt_offset'] . "' as comment_timestamp, UNIX_TIMESTAMP(comment_date_gmt) as comment_tstamp_gmt from " . $this->tables['comments'] . " where " . (!is_null($post_id) ? "comment_post_id=" . $post_id : '') . " and comment_approved='1' order by comment_date" . (!is_null($limit) ? " limit $limit" : ''); $db->query($q); return $db->all(); } function &getPostTags($postid=null, $force=false) { /* * caches all tags matching current post selection * * if you call this method manually before the parse methods, the * structures are cached and reused later */ if (is_null($this->_posttags) || $force) { if (!isset($this->posts_in)) $this->getPosts(); // force posts cache load if (empty($this->posts_in)) { $this->_posttags = array(); return $this->_posttags; } $tables =& $this->tables; $q = "SELECT DISTINCT post_id, tag_name AS name FROM {$tables['tags']} tag WHERE post_id IN ({$this->posts_in}) ORDER BY post_id, name"; $this->db->query($q); $posts_tags = array(); foreach ($this->db->all() as $tag) { $post_id = $tag['post_id']; if (!isset($posts_tags[$post_id])) $posts_tags[$post_id] = array(); $posts_tags[$post_id][] = $tag['name']; } $this->_posttags =& $posts_tags; } if (is_null($postid)) return $this->_posttags; elseif (isset($this->_posttags[$postid])) return $this->_posttags[$postid]; else return array(); } function getTagEncoded($tagname) { return(str_replace('%2F', '/', urlencode($tagname))); } function getTagPermalink($tagname) { return ( ($this->raw_urls) ? 'index.php?tag=' : $this->options['tag_prefix'] . '/') . $this->getTagEncoded($tagname); } function &getTags($force=false) { /* * gets all site tags * * if you call this method manually before the parse methods, the * structures are cached and reused later */ if (is_null($this->_tags) || $force) { $tables =& $this->tables; $q = "SELECT tag.tag_name AS name, COUNT(tag.post_id) as numposts, UNIX_TIMESTAMP(max(p.post_date_gmt)) + '" . $this->options['gmt_offset'] . "' as last_post_date, UNIX_TIMESTAMP(max(p.post_date_gmt)) as last_post_date_gmt FROM {$tables['tags']} tag INNER JOIN {$tables['posts']} p on tag.post_id=p.id WHERE (p.post_status='publish' OR p.post_status='static') AND p.post_date_gmt<='{$this->where_date}' GROUP BY tag.tag_name ORDER BY numposts DESC "; $this->db->query($q); $tags = array(); foreach ($this->db->all() as $tag) { $tag['encoded'] = $this->getTagEncoded($tag['name']); $tag['permalink'] = $this->getTagPermalink($tag['name']); $tags[$tag['name']] = $tag; } $this->_tags =& $tags; } return $this->_tags; } /*************************************************************************** * render methods **************************************************************************/ function startRender($content=null, $header=null, $sidebar=null, $footer=null) { if (!$this->_templates_set) { $templates =& $this->templates; if (is_null($content)) { switch ($this->context['type']) { case 'search': case 'author': case 'tag': case 'static': case 'post': $templates['index'] = $this->context['type'] . '.xml'; break; default: // already set in $this->templates; //$templates['index'] = 'index.xml'; } } else { $templates['index'] = $content; } if (!is_null($header)) $templates['header'] = $header; if (!is_null($sidebar)) $templates['sidebar'] = $sidebar; if (!is_null($footer)) $templates['footer'] = $footer; $this->_processPlugins('start_render', $templates); $this->tpl->setFile($templates); $this->_templates_set = true; } } function renderPost(&$post, $parse_block=true) { $this->current_post =& $post; $tpl =& $this->tpl; $context =& $this->context; $this->startRender(); if ($parse_block && !$this->_block_post) { // set blocks $tpl->setBlock('index', 'post', 'BLOCK_POST'); // TODO: make the following optional? $tpl->setBlock('post', 'day', 'BLOCK_DAY'); $tpl->setBlock('post', 'post_category', 'BLOCK_POST_CATEGORY'); $tpl->setBlock('post', 'post_more', 'BLOCK_POST_MORE'); $this->_block_post = true; } $post['skip_form'] = $post['skip_comments'] = false; /* * display the date label if necessary, or hide its template slot */ $static = false; switch ($context['type']) { case 'static': $static = true; case 'post': // hide the day block $tpl->setVar('BLOCK_DAY', ''); // hide the 'read more' link $tpl->setVar('BLOCK_POST_MORE', ''); // display comments $this->renderComments($post); break; default: // index pages, check date change if ($post['post_date'] != $this->_post_date) { // display the date $tpl->setVar('day_date', $post['post_date']); $tpl->parse('BLOCK_DAY', 'day'); $this->_post_date = $post['post_date']; $post['post_class_first'] = '_first'; } else { // hide the date $tpl->setVar('BLOCK_DAY', ''); $post['post_class_first'] = ''; } } /* * display post categories */ if (!$static) { // categories $multicategory = false; $categories =& $this->getCategories(); $i = count($post['categories']); $sep = $this->options['category_separator']; foreach ($post['categories'] as $post_category) { $tpl->setVar(array( 'post_cat_id' => $post_category, 'post_cat_name' => $categories[$post_category]['cat_name'], 'post_cat_nicename' => $categories[$post_category]['category_nicename'], 'post_cat_permalink' => $categories[$post_category]['category_permalink'], 'post_cat_separator' => ($i != 1 ? $sep : ''))); $tpl->parse('BLOCK_POST_CATEGORY', 'post_category', $multicategory); $multicategory = true; $i--; } } else { $tpl->setVar('BLOCK_POST_CATEGORY', ''); } $this->_processPlugins('parse_post', $post); $tpl->setVar($post); if ($context['type'] != 'post' && $context['type'] != 'static') { // hide or show the 'read more' link if (empty($post['post_more'])) $tpl->setVar('BLOCK_POST_MORE', ''); else $tpl->parse('BLOCK_POST_MORE', 'post_more'); } $tpl->parse('BLOCK_POST', 'post', true); } function renderComments(&$post) { $tpl =& $this->tpl; if (!$tpl->setBlock('index', 'comments', 'BLOCK_COMMENTS', false)) return; if ($post['skip_comments']) { $tpl->setVar('BLOCK_COMMENTS', ''); return; } $comments =& $this->getComments($post['post_id']); if (count($comments) == 0) { $tpl->setBlock('comments', 'comments_list', 'BLOCK_COMMENTS_LIST'); $tpl->setVar('BLOCK_COMMENTS_LIST', ''); $tpl->setVar( "comments_message_text", ($post['comment_status'] == 'open') ? $this->messages['comments_open_nocomments'] : $this->messages['comments_closed_nocomments']); } else { $tpl->setBlock('comments', 'comments_message', 'BLOCK_COMMENTS_MESSAGE'); $tpl->setVar('BLOCK_COMMENTS_MESSAGE', ''); $tpl->setBlock('comments', 'comment', 'BLOCK_COMMENT'); $tpl->setBlock('comment', 'author_url', 'BLOCK_COMMENT_AUTHOR_URL'); $i = 1; foreach ($comments as $comment) { $comment['comment_content'] = $this->paragrapher(stripslashes($comment['comment_content'])); $comment_timestamp = $comment['comment_timestamp']; $comment['comment_short_date'] = strftime($this->options['short_date_format'], $comment_timestamp); $comment['comment_short_time'] = strftime($this->options['short_time_format'], $comment_timestamp); $comment['comment_date'] = strftime($this->options['date_format'], $comment_timestamp); $comment['comment_time'] = strftime($this->options['time_format'], $comment_timestamp); $comment['comment_index'] = $i; $comment['comment_class'] = ($i % 2 == 0) ? 'comment_even' : 'comment_odd'; // render plugins $this->_processPlugins('parse_comment', $comment); $tpl->setVar($comment); if (empty($comment['comment_author_url'])) $tpl->setVar('BLOCK_COMMENT_AUTHOR_URL', $comment['comment_author']); else $tpl->parse('BLOCK_COMMENT_AUTHOR_URL', 'author_url'); $tpl->parse('BLOCK_COMMENT', 'comment', true); $i++; } } $tpl->parse('BLOCK_COMMENTS', 'comments'); } function renderSidebar() { if (is_string($this->_sidebar)) return $this->_sidebar; $this->startRender(); $tpl =& $this->tpl; if ($this->context['type'] == 'search') $tpl->setVar('search_keywords', htmlspecialchars($this->context['filter'], ENT_QUOTES, $this->options['charset'])); else $tpl->setVar('search_keywords', ''); if ($this->context['type'] == 'tag') { $tpl->setVar('search_tags', $this->context['filter']); $tpl->setVar('search_tags_encoded', str_replace('%2F', '/', urlencode($this->context['filter']))); } else { $tpl->setVar('search_tags', ''); $tpl->setVar('search_tags_encoded', ''); } // render plugins $plugin_data = ''; $this->_processPlugins('sidebar', $plugin_data); $this->_sidebar = $tpl->parse('SIDEBAR', 'sidebar'); } function renderPage($parse_posts=true, $parse_sidebar=true, $do_output=true) { $this->startRender(); $plugin_data = array( 'parse_posts'=>$parse_posts, 'parse_sidebar'=>$parse_sidebar, 'do_output'=>$do_output); $this->_processPlugins('pre_render', $plugin_data); $tpl =& $this->tpl; if ($plugin_data['parse_posts']) { $posts =& $this->getPosts(); if (count($posts) == 0) { $this->tpl->setBlock('index', 'post', 'BLOCK_POST'); if (!$tpl->setBlock('index', 'comments', 'BLOCK_COMMENTS', false)) $tpl->setVar('BLOCK_COMMENTS', ''); $this->tpl->setVar('BLOCK_POST', $this->messages['no_posts']); $tpl->setVar('BLOCK_COMMENTS', ''); // hide plugins $dummyvar = ''; $this->_processPlugins('parse_post', $dummyvar, true); } else { foreach ($posts as $k => $v) { $this->renderPost($posts[$k]); } } } if ($plugin_data['parse_sidebar']) { $this->renderSidebar(); } $tpl->setVar('title', $this->title); $tpl->parse('HEADER', 'header'); $tpl->parse('FOOTER', 'footer'); $this->_processPlugins('post_render', $out); $out =& $tpl->parse('MAIN', 'index'); // add a hook here if we ever need to parse the output before sending it // $this->_processPlugins('pre_output', $out); if (!is_null($this->cache) && $this->cache->active) $this->cache->setCache($out); if ($plugin_data['do_output']) echo $out; $this->_processPlugins('shutdown', $plugin_data); } /*************************************************************************** * utilities **************************************************************************/ function &getMailHelper() { if (!is_object($this->_mail_helper)) { require_once 'classes/MailHelper.php'; $o =& $this->options; $this->_mail_helper =& new MailHelper( $o['mail_from'], $o['mail_mailer'], (isset($o['mail_mailer_path']) ? $o['mail_mailer_path'] : null)); } return $this->_mail_helper; } /*************************************************************************** * comments stuff **************************************************************************/ function &insertComment($post_id, $now, $author, $email, $url, $comment, $type='', $xml_output=false) { $options =& $this->options; $tables =& $this->tables; $db =& $this->db; $comment = array( 'date' =>$now, 'author' =>$author, 'email' =>$email, 'url' =>$url, 'comment' =>$comment, 'type' =>$type, 'approved' =>'0'); $this->_processPlugins('insert_comment', $comment); /* // check for spam $spam_checker =& $this->_frontend->getSpamChecker(); $comment_status = $spam_checker->isSpam($author, $email, $url, $comment, $xml_output); */ // fix url if (!empty($url) && !preg_match('/^[a-zA-Z]+:\/\//', $comment['url'])) $comment['url'] = 'http://' . $url; $c_text = strip_tags($comment['comment'], $options['allowed_tags']); $c_text = $this->stripAttrs($c_text); $c_text = addslashes($c_text); $gmdate = gmdate("Y-m-d H:i:s", $comment['date']); $q = "insert into " . $tables['comments'] . " (" . "comment_post_ID, comment_author, comment_author_email, " . "comment_author_url, comment_author_IP, comment_date, " . "comment_date_gmt, comment_content, comment_approved, comment_agent, comment_type) " . "VALUES ($post_id, " . "'" . addslashes($comment['author']) . "', " . "'" . addslashes($comment['email']) . "', " . "'" . addslashes($comment['url']) . "', " . "'" . $_SERVER['REMOTE_ADDR'] . "', " . "'" . strftime("%Y-%m-%d %H:%M:%S", $comment['date']) . "', " . "'$gmdate', " . "'$c_text', '" . $comment['approved'] . "', " . "'" . $_SERVER['HTTP_USER_AGENT'] . "', " . "'" . $comment['type'] . "')"; $db->query($q, true); // trigger the cache garbage collector if we have an active cache if (!is_null($this->cache)) { if (isset($options['cache_actions_all_pages']) && $options['cache_actions_all_pages'] == '1') $this->cache->garbageCollect(null, true); else $this->cache->clearCachePostUri($_SERVER['REQUEST_URI'], true); } // TODO: move to the DB wrapper return mysql_insert_id(); } function stripAttrs($string, $allowed=array('title', 'href', '/')) { $m = array(); if (preg_match_all('/<([a-zA-Z]+)\s+([^>]+)>/sS', $string, $m, PREG_SET_ORDER)) { foreach ($m as $match) { $tag = '<' . $match[1]; foreach (preg_split('/\s+/', $match[2], -1, PREG_SPLIT_NO_EMPTY) as $attr) { $attr_tokens = explode('=', $attr); if (in_array($attr_tokens[0], $allowed)) { $tag .= ' ' . $attr; } } $tag .= '>'; $string = str_replace($match[0], $tag, $string); } } return $string; } function paragrapher(&$nltext) { if (substr($nltext, 0, 4) == "\t

") return($nltext); // already formatted if (strstr($nltext, "\r\n")) return("

" . str_replace("\r\n\r\n", "

\n

", $nltext) . "

"); else return("

" . str_replace("\n\n", "

\n

", $nltext) . "

"); } function setUserCookie($user_data) { $cookiepath = preg_replace('|https?://[^/]+|i', '', $this->options['url'] . '/'); foreach ($user_data as $k=>$v) { switch ($k) { case 'ud_name': case 'ud_email': case 'ud_url': break; default: unset($user_data[$k]); } } setcookie('lp_identity', serialize($user_data), time() + 30000000, $cookiepath); } function removeUserCookie() { $cookiepath = preg_replace('|https?://[^/]+|i', '', $this->options['url'] . '/'); setcookie('lp_identity', '', time() + 30000000, $cookiepath); } function redirectToPost($post_permalink, $message) { // redirect user so that he does not insert the comment twice header( "Location: " . $this->options['url'] . '/' . $post_permalink . '?' . 'message=' . urlencode($message) . '#add_comment'); exit; } function &_extractKeywords($q, $force=false) { if (!$force && !is_null($this->search_keywords)) return $this->search_keywords; // sanitize $q = trim($q); $q = preg_replace('/\s+/', ' ', $q); // extract keywords $keywords = array(); $inside = false; $keyword = ''; for ($i = 0; $i < strlen($q); $i++) { $c = $q[$i]; if ($inside) { if ($c == '"') $inside = false; else $keyword .= $c; } else { switch ($c) { case ' ': if (!empty($keyword)) $keywords[] = addslashes(strtolower($keyword)); $keyword = ''; break; case '"': $inside = true; break; default: $keyword .= $c; } } } if (!empty($keyword)) $keywords[] = addslashes(strtolower($keyword)); $this->search_keywords =& $keywords; return $keywords; } /*************************************************************************** * feeds stuff **************************************************************************/ function doConditionalGet($tstamp) { /* A PHP implementation of conditional get for LightPress, see also * http://fishbowl.pastiche.org/archives/001132.html * http://simon.incutio.com/archive/2003/04/23/conditionalGet * * for HTTP/1.1 dates see RFC2616#3.3.1 * * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format * All HTTP date/time stamps MUST be represented in Greenwich Mean Time * (GMT), without exception. * HTTP/1.1 clients and servers that parse the date value MUST accept * all three formats (for compatibility with HTTP/1.0), though they MUST * only generate the RFC 1123 format for representing HTTP-date values * in header fields. * * and #14.25 for If-Modified-Since * * Note: When handling an If-Modified-Since header field, some * servers will use an exact date comparison function, rather than a * less-than function, for deciding whether to send a 304 (Not * Modified) response. To get best results when sending an If- * Modified-Since header field for cache validation, clients are * advised to use the exact date string received in a previous Last- * Modified header field whenever possible. * * etc. * */ // ETag is any quoted string $etag = '"'. $tstamp .'"'; // RFC1123 date, see http://bugs.php.net/bug.php?id=31842 if (version_compare(PHP_VERSION, "4.3.11", ">=")) $format = 'r'; else $format = 'D, d M Y H:i:s O'; $rfc1123 = substr(date($format, $tstamp), 0, -5) . 'GMT'; // RFC1036 date $rfc1036 = date('l, d-M-y H:i:s ', $tstamp) . 'GMT'; // asctime $ctime = date('D M j H:i:s', $tstamp); // Send the headers header("Last-Modified: $rfc1123"); header("ETag: $etag"); // See if the client has provided the required headers $if_modified_since = $if_none_match = false; if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) $if_modified_since = stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']); if(isset($_SERVER['HTTP_IF_NONE_MATCH'])) $if_none_match = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']); if (!$if_modified_since && !$if_none_match) { // both are missing return $rfc1123; } // At least one of the headers is there - check them // check etag if it's there and there's no if-modified-since if ($if_none_match) { if ($if_none_match != $etag) { // etag is there but doesn't match return $rfc1123; } if (!$if_modified_since && ($if_none_match == $etag)) { header('HTTP/1.0 304 Not Modified'); exit; } } if ($if_modified_since) { // check if-modified-since foreach (array($rfc1123, $rfc1036, $ctime) as $d) { if ($d == $if_modified_since) { // Nothing has changed since their last request - serve a 304 and exit header('HTTP/1.0 304 Not Modified'); exit; } } } // return $rfc1123 as it may be useful later, eg 'lastBuildDate' for RSS2 return $rfc1123; } function ISO8601($tstamp) { return date("Y-m-d\TH:i:s", $tstamp) . '+00:00'; } /*************************************************************************** * moved from attributes to (static) methods for the WP admin plugins **************************************************************************/ function getCriticalOptions() { return array('basedir', 'url', 'mail_from'); } function getBaseOptions() { return array( //'basedir' => dirname(__FILE__), // can't live without //'url' => 'http://myhost.org', // can't live without 'wp_url' => 'http://myhost.org/wordpress', // set by Frontend if not in config.php 'blogname' => 'Blog Name', 'shortname' => 'short_name', 'description' => 'Description for atom feeds.', 'copyright_notice' => 'Copyright notice for atom feeds.', 'posts_per_page' => 12, 'posts_per_rss' => 10, 'date_format' => '%A %d %B %Y', 'short_date_format' => '%d %b %Y', 'time_format' => '%H:%M:%S', 'short_time_format' => '%H:%M', 'archive_label' => '%B %Y', 'lang' => 'en_US', 'charset' => 'UTF-8', // UTF-8, ISO-8859-1, etc. 'template' => 'elastic_minimal', 'mail_mailer' => false, // false or empty to use PHP's mail() function //'mail_from' => 'me@my.host', // can't live without 'mail_on_comment' => true, 'allowed_tags' => '


', 'post_prefix' => 'post/{post_name}', 'category_prefix' => 'category', 'archives_prefix' => 'archives/{year}/{monthnum}', 'pages_prefix' => '', 'pages_suffix' => '', 'search_prefix' => 'search', 'author_prefix' => 'author', 'tag_prefix' => 'tag', 'category_separator'=> ',', 'comment_spam_kill' => true, // true kills the supposed spam, false inserts it waiting for moderation 'comment_spam_mail' => true, // true mail on kills only 'plugins' => array() ); } function getDefaultPlugins() { // try to list them all here so we can include the template tags for inactive plugins return array( // plugin active contexts args 'AboutContext' =>array(LP_CONTEXT_CATEGORY | LP_CONTEXT_ARCHIVES, array()), 'AboutMe' =>array(LP_CONTEXT_INDEX, array()), 'AboutPost' =>array(LP_CONTEXT_POST, array()), 'AdminOptions' =>array(LP_CONTEXT_ALL, array()), 'ArchivesList' =>array(0, array()), 'ArchivesListExtended' =>array(LP_CONTEXT_ALL, array()), 'AuthorIndex' =>array(LP_CONTEXT_AUTHOR, array()), 'CategoriesList' =>array(0, array()), 'CategoriesListExtended' =>array(LP_CONTEXT_ALL, array()), 'CommentSpam' =>array(LP_CONTEXT_POST, array()), 'Delicious' =>array(0, array()), 'Flickr' =>array(0, array()), 'HeaderAd' =>array(0, array()), 'Links' =>array(LP_CONTEXT_ALL, array()), 'NestedPages' =>array(0, array()), 'Pagination' =>array(LP_CONTEXT_ALL, array()), 'PostComment' =>array(LP_CONTEXT_POST, array()), 'PostRelated' =>array(LP_CONTEXT_POST, array()), 'PostsList' =>array(LP_CONTEXT_ALL ^ LP_CONTEXT_INDEX, array()), 'PostTags' =>array(LP_CONTEXT_ALL, array()), 'SearchIndex' =>array(LP_CONTEXT_SEARCH, array()), 'TagCloud' =>array(LP_CONTEXT_STATIC, array()), 'TopCommented' =>array(LP_CONTEXT_ALL, array()), ); } function getVersion() { return '1.2.0-a2'; } function getPermalinkVerbs() { return array( 'post' => array( 'year' => '%Y', 'monthnum' => '%m', 'day' => '%d', 'hour' => '%H', 'minute' => '%M', 'second' => '%S', 'postname' => '%%1$s', 'post_name' => '%%1$s', 'post_id' => '%%2$s'), // 'category' => '', // unsupported for now, since it requires an additional JOIN in plugins // 'author' => ''), // unsupported for now, since it requires an additional JOIN in plugins 'archives' => array( 'year' => '%Y', 'monthnum' => '%m', 'day' => '%d')); } function prefixToPermalinkStruct($value, $context='post') { if (empty($value)) return $value; $permalink_verbs = Frontend::getPermalinkVerbs(); if (!isset($permalink_verbs[$context])) return $value; $matches = array(); preg_match_all('/{([^}]+)}/', $value, $matches); foreach ($matches[1] as $i=>$verb) { if (isset($permalink_verbs[$context][$verb])) { $value = str_replace('{' . $verb . '}', $permalink_verbs[$context][$verb], $value); } } return $value; } function raiseError($message, $method, $line, $type=E_USER_WARNING) { trigger_error( sprintf("%s.%s() line %d: %s", get_class($this), $method, $line, $message), $type); } } ?>