NP_Headerを改造してみた

NP_Headerを導入してみたものの・・・

  • bulkfeeds の APIを使った形態素解析が動かない
  • plugin_headerのレコードが記事にアクセスされるたび、REPLACEクエリで削除→登録されるオーバーヘッドが発生する

などの問題があったので、プログラムを改造してみました。
久しぶりにPHPのコードを触ったので苦労しましたが、期待した結果を得られることができました。
形態素解析にはYahooのWEB APIを使いました。
※利用するにはアプリケーションIDの登録が必要です。

<?php
/**
* NP_Header - Sends some HTTP headers, and outputs meta elements for Nucleus CMS
*
* Copyright (c) 2004-2008, kalm
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* @package NP_Header
* @author  kalm
* @copyright 2004-2008 kalm, 2009 admin
* @license http://opensource.org/licenses/gpl-license.php GNU General Public License
* @version 2.0
* @require PHP 4.3.0 and higher, Nucleus CMS 2.5 and higher
*/
/**
* @ignore
*/
defined('PHP_EOL') || define('PHP_EOL', "n");
/**
* NP_Header class.
*/
class NP_Header extends NucleusPlugin {
/**
* Returns the name of the plugin.
*
* @access public
* @return string
*/
function getName()   {
return 'Header';
}
/**
* Returns the name of author of the plugin.
*
* @access public
* @return string
*/
function getAuthor() {
return 'kalm';
}
/**
* Returns the URL of the site where the plugin can be downloaded.
*
* @access public
* @return string
*/
function getURL() {
return 'http://funktor.org/';
}
/**
* Returns a longer description of the plugin.
*
* @access public
* @return string
*/
function getDescription() {
return 'Sends some HTTP headers, and outputs meta elements.';
}
/**
* Returns the current version of the plugin.
*
* @access public
* @return string
*/
function getVersion() {
return '2.03';
}
/**
* Returns the minimum required Nucleus CMS version.
*
* @access public
* @return string
*/
function getMinNucleusVersion() {
return '250';
}
/**
* Checks if a plugin supports a certain feature.
*
* @access public
* @param string $feature name of the feature
* @return int 1 if the feature is reported; 0 otherwise
*/
function supportsFeature($what) {
switch ($what) {
case 'SqlTablePrefix':
return 1;
default:
return 0;
}
}
/**
* This method should return an array of database tables that the plugin has created.
*
* @access public
* @return array
*/
function getTableList() {
return array(sql_table('plugin_header'));
}
/**
* Plugins can subscribe to events.
*
* @access public
* @return array
*/
function getEventList() {
return array('PreSendContentType', 'PostAddItem', 'PreUpdateItem',
'PostAddComment', 'PostPluginOptionsUpdate', 'AddItemFormExtras',
'EditItemFormExtras', 'PreDeleteItem', 'PostDeleteCategory',
'PostDeleteBlog', 'PostDeleteComment', 'PreDeletePlugin',
'PostAddCategory', 'PostAddPlugin', 'PostMoveItem',
'PostMoveCategory');
}
/**
* This method gets called on the moment the plugin is installed.
*
* @access public
*/
function install() {
$this->createOption('use_sitename', 'Use site name instead of blog name to Title?', 'yesno', 'no');
$this->createOption('no_cache', 'No cache', 'yesno', 'no');
$this->createOption('use_yahoo_webapi', 'Acquire keywords automatically, with using Yahoo WEB API', 'yesno', 'no');
$this->createOption('max_keywords', 'Max keywords acquired with Yahoo WEB API', 'text', '8');
$this->createBlogOption('tpl_http', 'HTTP headers template', 'textarea',
'Content-Type: text/html; charset=<%charset%>' . PHP_EOL .
'Content-Script-Type: text/javascript' . PHP_EOL .
'Content-Style-Type: text/css' . PHP_EOL .
'<%if(language)%>Content-Language: <%language%><%endif%>' . PHP_EOL .
'Last-Modified: <%last_modified%>' . PHP_EOL .
'X-Generator: <%version%>');
$this->createBlogOption('tpl_html', 'HTML template (e.g. meta elements)', 'textarea',
'<%if(title)%><meta name="Title" content="<%title%>" /><%endif%>' . PHP_EOL .
'<%if(description)%><meta name="Description" content="<%description%>" /><%endif%>' . PHP_EOL .
'<%if(keywords)%><meta name="Keywords" content="<%keywords%>" /><%endif%>' . PHP_EOL .
'<meta name="Classification" content="General" />' . PHP_EOL .
'<meta name="Rating" content="General" />' . PHP_EOL .
'<meta name="Doc-Class" content="Living Document" />' . PHP_EOL .
'<meta name="Revisit-After" content="7 days" />' . PHP_EOL .
'<%if(robots)%><meta name="Robots" content="<%robots%>" /><%endif%>' . PHP_EOL .
'<meta name="Generator" content="<%version%>" />');
$this->createBlogOption('language', 'Default language (ISO 639 language codes)', 'text', 'ja');
$this->createBlogOption('keywords', 'Default keywords (comma-separated)', 'text');
$this->createBlogOption('robots', 'Default robots control value', 'text', 'ALL');
$this->createBlogOption('yahoo_appid', 'Yahoo WEB APP ID', 'text', '');
$this->createOption('del_uninstall', 'Delete a table on uninstall?', 'yesno', 'no');
sql_query('CREATE TABLE IF NOT EXISTS ' . sql_table('plugin_header') . " (
`itemid` int(11) NOT NULL,
`description` varchar(255) NOT NULL default '',
`keywords` varchar(255) NOT NULL default '',
`language` varchar(255) NOT NULL default '',
`last_modified` datetime NOT NULL default '0000-00-00 00:00:00',
`modifier` varchar(255) NOT NULL default '',
PRIMARY KEY (itemid))
");
/* for compatibility with NP_Header 1.21 and lower */
if (mysql_num_rows(sql_query('SHOW TABLES LIKE '' . sql_table('plugin_meta_keywords') . ''')) > 0) {
$result = sql_query('SELECT * FROM ' . sql_table('plugin_meta_keywords'));
while (($row = mysql_fetch_object($result)) !== FALSE) {
$this->_setItemKeywords($row->itemid, $row->keywords);
}
sql_query('DROP TABLE ' . sql_table('plugin_meta_keywords'));
}
}
/**
* Called when the plugin is uninstalled.
*
* @access public
*/
function unInstall() {
if ($this->getOption('del_uninstall') == 'yes') {
sql_query('DROP TABLE IF EXISTS ' . sql_table('plugin_header'));
}
$this->deleteOption('del_uninstall');
$this->deleteBlogOption('tpl_http');
$this->deleteBlogOption('tpl_html');
$this->deleteBlogOption('language');
$this->deleteBlogOption('keywords');
$this->deleteBlogOption('robots');
$this->deleteBlogOption('yahoo_appid');
$this->deleteOption('use_sitename');
$this->deleteOption('no_cache');
$this->deleteOption('use_yahoo_webapi');
$this->deleteOption('max_keywords');
}
/**
* When a plugin wants to allow user interaction, it can allow actions through action.php.
*
* @access public
* @param string $type an optional message type
*/
function doAction($type) {
if (($type == 'lirs') || ($type == 'lirs_gzip')) {
/**
* Outputs LIRS (Last modified Information Relaying Specification)
* @see http://aniki.haun.org/natsu/LIRS.html
*/
global $manager, $nucleus;
$time = 0;
$localzone = date('Z');
$utime = time() - $localzone;
$length = 0;
$uri = '';
$title = '';
$modifier = '';
$result = sql_query('SELECT * FROM ' . sql_table('plugin_header') .
' ORDER BY last_modified DESC LIMIT 1');
if (mysql_num_rows($result) > 0) {
$row = mysql_fetch_object($result);
$itemid = $row->itemid;
$time = strtotime($row->last_modified);
$modifier = $row->modifier;
$blog =& $manager->getBlog(getBlogIDFromItemID($itemid));
if ($blog) {
$uri = $blog->getURL();
$length = strlen(@file_get_contents($uri));
$title = $blog->getName();
}
}
$content = 'LIRS,' . $time . ',' . $utime . ',' . $localzone . ',' .
$length . ',' . $uri . ',' . $title . ',' . $modifier . ',' .
$uri . ',Nucleus CMS ' . $nucleus['version'] . ",n";
$content = mb_convert_encoding($content, 'EUC-JP', _CHARSET);
if ($type == 'lirs_gzip') {
$content = gzcompress($content);
}
echo $content;
}
}
/**
* When plugins are called using the <%plugin(...)%>-skinvar, this method will be called.
*
* @access public
* @param string $skinType the type of skin
*/
function doSkinVar($skinType)
{
global $CONF, $manager, $blog, $itemid;
if (!empty($blog)) {
$b =& $blog;
} else {
$b =& $manager->getBlog($CONF['DefaultBlog']);
}
$blogid = $b->getID();
$language = $this->getBlogOption($blogid, 'language');
$last_modified = $this->_getLastModified();
if (($this->getOption('use_sitename') == 'yes') && isset($CONF['SiteName'])) {
$title = $CONF['SiteName'];
} else {
$title = $b->getName();
}
switch ($skinType) {
case 'item':
$this->_checkItemData($itemid);
$language = $this->_getItemLanguage($itemid);
$description = $this->_getItemDescription($itemid);
$keywords = $this->_getItemKeywords($itemid);
break;
case 'search':
case 'error':
case 'imagepopup':
$description = '';
$keywords = 'DONOTSEARCH';
break;
default:
$description = $b->getDescription();
$keywords = $this->getBlogOption($blogid, 'keywords');
break;
}
$robots = $this->getBlogOption($blogid, 'robots');
if ($keywords == 'DONOTSEARCH') {
$keywords = '';
$robots = 'NOINDEX';
}
$template = $this->getBlogOption($blogid, 'tpl_html');
$trans = array(
'<%language%>' => $language,
'<%last_modified%>' => $last_modified,
'<%title%>' => $title,
'<%description%>' => $description,
'<%keywords%>' => $keywords,
'<%robots%>' => $robots,
);
echo $this->_parseTemplate($template, $trans);
}
/**
* After adding a comment to the database.
*
* @access public
* @param array $data comment data
*/
function event_PostAddComment($data) {
$c = $data['comment'];
$this->_setItemLastModified($c['itemid'], $c['timestamp'], $c['user']);
}
/**
* After an item has been added to the database.
*
* @access public
* @param array $data item data
*/
function event_PostAddItem($data) {
global $manager;
$itemid = $data['itemid'];
$item =& $manager->getItem($itemid, 0, 0);
if ($item) {
$author =& MEMBER::createFromID($item['authorid']);
$this->_setItemData($itemid, requestVar('item_description'),
requestVar('item_keywords'), requestVar('item_language'),
$item['timestamp'], $author->getRealName());
}
}
/**
* Immediately before an item gets updates in the database.
*
* @access public
* @param array $data item data
*/
function event_PreUpdateItem($data) {
global $manager;
$itemid = $data['itemid'];
$item =& $manager->getItem($itemid, 0, 0);
if ($item) {
$author =& MEMBER::createFromID($item['authorid']);
$this->_setItemData($itemid, requestVar('item_description'),
requestVar('item_keywords'), requestVar('item_language'),
time(), $author->getRealName());
}
}
/**
* Somewhere inside the add item page or bookmarklet.
*
* @access public
* @param array $data data
*/
function event_AddItemFormExtras($data) {
echo '<h3>' . $this->getName() . '</h3>
<p><label for="item_description">Item description</label>:<br />
<input type="text" name="item_description" id="item_description" size="60" maxlength="255" value="" /></p>
<p><label for="item_keywords">Item keywords (comma-separated), or "DONOTSEARCH"</label>:<br />
<input type="text" name="item_keywords" id="item_keywords" size="60" maxlength="255" value="" /></p>
<p><label for="item_language">Item language (ISO 639 language codes; when differing from blog)</label>:<br />
<input type="text" name="item_language" id="item_language" size="10" maxlength="5" value="" /></p>';
}
/**
* Somewhere inside the edit item page or bookmarklet.
*
* @access public
* @param array $data data
*/
function event_EditItemFormExtras($data) {
echo '<h3>' . $this->getName() . '</h3>
<p><label for="item_description">Item description</label>:<br />
<input type="text" name="item_description" id="item_description" size="60" maxlength="255" value="' . $this->_getItemDescription($data['itemid']) . '" /></p>
<p><label for="item_keywords">Item keywords (comma-separated), or "DONOTSEARCH"</label>:<br />
<input type="text" name="item_keywords" id="item_keywords" size="60" maxlength="255" value="' . $this->_getItemKeywords($data['itemid']) . '" /></p>
<p><label for="item_language">Item language (ISO 639 language codes; when differing from blog)</label>:<br />
<input type="text" name="item_language" id="item_language" size="10" maxlength="5" value="' . $this->_getItemLanguage($data['itemid']) . '" /></p>';
}
/**
* After the options for a plugin have been updated.
*
* @access public
* @param array $data plugin options data
*/
function event_PostPluginOptionsUpdate($data) {
$this->_setLastModified();
}
/**
* Immediately before an item gets deleted in the database.
*
* @access public
* @param int $itemid itemid
*/
function event_PreDeleteItem($itemid) {
$this->_setLastModified();
}
/**
* Immediately after a category has been deleted from the database.
*
* @access public
* @param int $catid catid
*/
function event_PostDeleteCategory($catid) {
$this->_setLastModified();
}
/**
* Immediately after a blog has been deleted from the database.
*
* @access public
* @param int $blogid blogid
*/
function event_PostDeleteBlog($blogid) {
$this->_setLastModified();
}
/**
* Immediately after a comment has been deleted from the database.
*
* @access public
* @param int $commentid commentid
*/
function event_PostDeleteComment($commentid) {
$this->_setLastModified();
}
/**
* Immediately after a plugin has been deleted from the database.
*
* @access public
* @param int $plugid plugid
*/
function event_PreDeletePlugin($plugid) {
$this->_setLastModified();
}
/**
* Immediately after a new category has been created in the database.
*
* @access public
* @param array $data category data
*/
function event_PostAddCategory($data) {
$this->_setLastModified();
}
/**
* Immediately after a plugin has been added.
*
* @access public
* @param array $data plugin data
*/
function event_PostAddPlugin($data) {
$this->_setLastModified();
}
/**
* Immediately after an item has been moved to another blog/category.
*
* @access public
* @param array $data item data
*/
function event_PostMoveItem($data) {
$this->_setLastModified();
}
/**
* Immediately after a catgeory has been moved to another blog.
*
* @access public
* @param array $data catgeory data
*/
function event_PostMoveCategory($data) {
$this->_setLastModified();
}
/**
* Immediately before a content type is being set in the HTTP header.
*
* @access public
* @param array $data data
*/
function event_PreSendContentType(&$data) {
if (headers_sent() || ($data['pageType'] != 'skin')
|| (strtolower(substr(php_sapi_name(), 0, 3)) == 'cgi')) {
return;
}
$template = $this->getBlogOption($blogid, 'tpl_http');
if (!empty($template)) {
global $CONF, $manager, $blog, $itemid;
if (!empty($blog)) {
$b =& $blog;
} else {
$b =& $manager->getBlog($CONF['DefaultBlog']);
}
$blogid = $b->getID();
$language = $this->getBlogOption($blogid, 'language');
$last_modified = $this->_getLastModified();
if ($itemid) {
$language = $this->_getItemLanguage($itemid);
}
$trans = array(
'<%language%>' => $language,
'<%last_modified%>' => $last_modified,
);
$template = $this->_parseTemplate($template, $trans);
$template = preg_split('/r?n/', $template, -1, PREG_SPLIT_NO_EMPTY);
foreach ($template as $h) header($h);
}
if ($this->getOption('no_cache') == 'yes') {
$last_modified = gmdate('D, d M Y H:i:s');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified:' . $last_modified);
header('ETag: ' . md5($last_modified));
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');
} else {
global $itemid;
if (!empty($itemid)) {
$last_modified = $this->_getItemLastModified($itemid);
} else {
$last_modified = $this->_getLastModified();
}
$this->_doConditionalGet($last_modified);
}
}
/**
* Check item data Records.
*
* @access private
* @param int $itemid itemid
*/
function _checkItemData($itemid) {
global $manager;
$result = sql_query('SELECT itemid FROM ' . sql_table('plugin_header') .
' WHERE (itemid = '' . ((int)$itemid) . '')');
if (!mysql_num_rows($result)) {
$item =& $manager->getItem($itemid, 0, 0);
sql_query('INSERT INTO ' . sql_table('plugin_header') .
' (itemid, last_modified) VALUES ('' . ((int)$itemid) .
'', '' . mysqldate($item['timestamp']) . '')');
}
}
/**
* Sets item data.
*
* @access private
* @param int $itemid itemid
* @param string $description description
* @param string $keywords keywords
* @param string $language language
* @param int $last_modified last_modified
*/
function _setItemData($itemid, $description, $keywords, $language, $last_modified, $modifier) {
sql_query('REPLACE INTO ' . sql_table('plugin_header') .
' (itemid, description, keywords, language, last_modified, modifier) VALUES ('' .
((int)$itemid) . '', '' . addslashes($description) . '', '' .
addslashes($keywords) . '', '' . addslashes($language) . '', ' .
mysqldate($last_modified) . ', '' . addslashes($modifier) . '')');
}
/**
* Sets item description.
*
* @access private
* @param int $itemid itemid
* @param string $description description
*/
function _setItemDescription($itemid, $description) {
sql_query('UPDATE ' . sql_table('plugin_header') .
' SET description = '' . addslashes($description) . ''' .
' WHERE (itemid = '' . ((int)$itemid) . '')');
}
/**
* Gets item description.
*
* @access private
* @param int $itemid itemid
* @return string
*/
function _getItemDescription($itemid) {
global $manager, $blog;
$description = '';
$result = sql_query('SELECT description FROM ' . sql_table('plugin_header') .
' WHERE (itemid = '' . ((int)$itemid) . '')');
if (mysql_num_rows($result) > 0) {
$row = mysql_fetch_object($result);
$description = $row->description;
}
if (!empty($description)) {
return $description;
}
$item =& $manager->getItem($itemid, 0, 1);
if (!empty($item)) {
$description = strip_tags($item['body']);
$description = preg_replace('/[rnt�40]+/', ' ', $description);
$description = shorten($description, 250, ' ...');
$description = htmlspecialchars($description);
$this->_setItemDescription($itemid, $description);
return $description;
}
if (!empty($blog)) {
$b =& $blog;
} else {
$b =& $manager->getBlog($CONF['DefaultBlog']);
}
return $b->getDescription();
}
/**
* Sets item keywords.
*
* @access private
* @param int $itemid itemid
* @param string $keywords keywords
*/
function _setItemKeywords($itemid, $keywords) {
sql_query('UPDATE ' . sql_table('plugin_header') .
' SET keywords = '' . addslashes($keywords) . ''' .
' WHERE (itemid = '' . ((int)$itemid) . '')');
}
/**
* Gets item keywords.
*
* @access private
* @param int $itemid itemid
* @return string
*/
function _getItemKeywords($itemid) {
global $CONF, $manager, $blog;
$keywords = '';
$result = sql_query('SELECT keywords FROM ' . sql_table('plugin_header') .
' WHERE (itemid = '' . ((int)$itemid) . '')');
if (mysql_num_rows($result) > 0) {
$row = mysql_fetch_object($result);
$keywords = $row->keywords;
}
if (!empty($keywords)) return $keywords;
if ($this->getOption('use_yahoo_webapi') == 'yes') {
if (!empty($blog)) {
$b =& $blog;
} else {
$b =& $manager->getBlog($CONF['DefaultBlog']);
}
$blogid = $b->getID();
$item =& $manager->getItem($itemid, 0, 1);
if (!empty($item)) {
$url = 'http://jlp.yahooapis.jp/MAService/V1/parse';
$appid = $this->getBlogOption($blogid, 'yahoo_appid');
$sentence = strip_tags($item['body'] . $item['more']);
$data = array(
'appid'       => $appid,
'results'     => 'uniq',
'uniq_filter' => '9',
'sentence'    => $sentence,
);
$options = array('http' => array(
'method'  => 'POST',
'header'  => 'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query($data)
));
$result = file_get_contents($url, false, stream_context_create($options));
if ( $ResultSet = simplexml_load_string($result) ) {
foreach ($ResultSet->uniq_result->word_list->word as $val) {
$surface = (string)$val->surface;
$items[$surface] = (int)$val->count;
}
arsort($items);
for($i=0; $i < $this->getOption('max_keywords') && current($items); $i++) {
$words[] = key($items);
next($items);
}
if (count($words) > 0) {
$keywords = implode(', ', $words);
$this->_setItemKeywords($itemid, $keywords);
return $keywords;
}
}
}
}
return $this->getBlogOption(getBlogIDFromItemID($itemid), 'keywords');
}
/**
* Sets item language.
*
* @access private
* @param int $itemid itemid
* @param string $language language
*/
function _setItemLanguage($itemid, $language) {
sql_query('UPDATE ' . sql_table('plugin_header') .
' SET language = '' . addslashes($language) . ''' .
' WHERE (itemid = '' . ((int)$itemid) . '')');
}
/**
* Gets item language.
*
* @access private
* @param int $itemid itemid
* @return string
*/
function _getItemLanguage($itemid) {
global $CONF, $manager, $blog;
$language = '';
$result = sql_query('SELECT language FROM ' . sql_table('plugin_header') .
' WHERE (itemid = '' . ((int)$itemid) . '')');
if (mysql_num_rows($result) > 0) {
$row = mysql_fetch_object($result);
$language = $row->language;
}
if (empty($language)) {
if (!empty($blog)) {
$b =& $blog;
} else {
$b =& $manager->getBlog($CONF['DefaultBlog']);
}
$blogid = $b->getID();
$language = $this->getBlogOption($blogid, 'language');
if ( $language ) $this->_setItemLanguage($itemid, $language);
}
return $language;
}
/**
* Sets item last modified.
*
* @access private
* @param int $itemid itemid
* @param int $time time
* @param string $modifier modifier
*/
function _setItemLastModified($itemid, $time = -1, $modifier)
{
if ($time == -1) $time = time();
sql_query('UPDATE ' . sql_table('plugin_header') .
' SET last_modified = ' . mysqldate($time) .
', modifier = '' . addslashes($modifier) . ''' .
' WHERE (itemid = '' . ((int)$itemid) . '')');
}
/**
* Gets item last modified.
*
* @access private
* @param int $itemid itemid
* @return int
*/
function _getItemLastModified($itemid) {
$result = sql_query('SELECT * FROM ' . sql_table('plugin_header') .
' WHERE (itemid = '' . ((int)$itemid) . '')');
if (mysql_num_rows($result) > 0) {
$row = mysql_fetch_object($result);
return strtotime($row->last_modified);
}
return time();
}
/**
* Sets last modified information.
*
* @access public
* @param int $time time
* @param string $modifier modifier
*/
function _setLastModified($time = -1, $modifier = '') {
if ($time == -1) $time = time();
$query = 'UPDATE ' . sql_table('plugin_header') .
' SET last_modified = ' . mysqldate($time);
if (!empty($modifier)) {
$query .= ', modifier = '' . addslashes($modifier) . ''';
}
sql_query($query);
}
/**
* Gets last modified information.
*
* @access public
* @return int timestamp
*/
function _getLastModified() {
$result = sql_query('SELECT * FROM ' . sql_table('plugin_header') .
' ORDER BY last_modified DESC LIMIT 1');
if (mysql_num_rows($result) > 0) {
$row = mysql_fetch_object($result);
return strtotime($row->last_modified);
}
return time();
}
/**
* A PHP implementation of conditional get, see
* @link http://fishbowl.pastiche.org/archives/001132.html
*
* @access private
* @param int $last_modified last modified
*/
function _doConditionalGet($last_modified) {
$last_modified = gmdate('D, d M Y H:i:s', $last_modified);
$etag = '"' . md5($last_modified) . '"';
header('Last-Modified: ' . $last_modified);
header('ETag: ' . $etag);
$if_modified_since = stripslashes(serverVar('HTTP_IF_MODIFIED_SINCE'));
$if_none_match = stripslashes(serverVar('HTTP_IF_NONE_MATCH'));
if (empty($if_modified_since) && empty($if_none_match)) return;
if (!empty($if_none_match) && ($if_none_match != $etag)) return;
if (!empty($if_modified_since) && ($if_modified_since != $last_modified)) return;
header('HTTP/1.1 304 Not Modified');
exit;
}
/**
* Parses header template.
*
* @access private
* @param string $template template
* @param array $vars additional variables
* @return string parsed template
*/
function _parseTemplate($template, $vars) {
global $nucleus;
$trans = array_merge(array(
'<%charset%>' => _CHARSET,
'<%version%>' => 'Nucleus CMS ' . $nucleus['version']
), $vars);
$template = preg_replace('/<%if((w+))%>n?((?:(?>(?:(?!(<%if(w+)%>|<%endif%>)).)*)|(?R))*)<%endif%>n?/se',
'str_replace('\\"','"',(!isset($trans['<%\1%>'])||empty($trans['<%\1%>']))?'':'\2')',
$template);
return strtr($template, $trans);
}
}
?>