function event_hook($event, &$bag, &$eventData) { global $serendipity; $hooks =& $bag->get('event_hooks'); if (isset($hooks[$event])) { switch ($event) { case 'frontend_configure': if (isset($serendipity['COOKIE']['user_template']) && !isset($_REQUEST['user_template'])) { $_REQUEST['user_template'] = $serendipity['COOKIE']['user_template']; } if (isset($_REQUEST['user_template']) && in_array($_REQUEST['user_template'], serendipity_fetchTemplates())) { $_SESSION['serendipityUseTemplate'] = $_REQUEST['user_template']; serendipity_setCookie('user_template', $_REQUEST['user_template'], false); } if (isset($_SESSION['serendipityUseTemplate'])) { $templateInfo = serendipity_fetchTemplateInfo($_SESSION['serendipityUseTemplate']); $eventData['template'] = $_SESSION['serendipityUseTemplate']; $eventData['template_engine'] = isset($templateInfo['engine']) ? $templateInfo['engine'] : $serendipity['defaultTemplate']; $serendipity['smarty_vars']['head_link_stylesheet'] = $serendipity['baseURL'] . 'serendipity.css.php?switch=' . $_REQUEST['user_template']; } return true; break; default: return false; } } else { return false; } }
function generate_content(&$title) { global $serendipity; $title = $this->get_config('title', $this->title); $url = serendipity_currentURL(true); echo '<form id="theme_chooser" action="' . $url . '" method="post">'; echo '<select name="user_template" onchange="document.getElementById(\'theme_chooser\').submit();">'; foreach (serendipity_fetchTemplates() as $template) { $templateInfo = serendipity_fetchTemplateInfo($template); echo '<option value="' . $template . '" ' . (serendipity_get_config_var('template', 'default') == $template ? 'selected="selected"' : '') . '>' . substr($templateInfo['name'], 0, 25) . '</option>'; } echo '</select>'; if ($this->get_config('show_submit', 'false') == 'true') { echo '<input type="submit" name="submit" value="' . GO . '" size="4" />'; } echo '</form>'; }
function event_hook($event, &$bag, &$eventData, $addData = null) { global $serendipity; $hooks =& $bag->get('event_hooks'); if (isset($hooks[$event])) { switch ($event) { case 'frontend_configure': if (defined('IN_serendipity_admin') && IN_serendipity_admin) { // Admin shall not have switchable themes. return true; } if (isset($serendipity['COOKIE']['user_template']) && !isset($_REQUEST['user_template'])) { $_REQUEST['user_template'] = $serendipity['COOKIE']['user_template']; } if (isset($_REQUEST['user_template']) && in_array($_REQUEST['user_template'], serendipity_fetchTemplates())) { # Specific themes can be blacklisted for viewing. Enter the names of those, one per line. $blacklisted = $has_blacklist = false; if (file_exists(dirname(__FILE__) . '/blacklist.txt')) { $_blacklist = explode("\n", file_get_contents(dirname(__FILE__) . '/blacklist.txt')); $blacklist = array(); $has_blacklist = true; foreach ($_blacklist as $idx => $blackline) { $blackline = trim($blackline); if (empty($blackline)) { continue; } if ($blackline[0] == '#') { continue; } $blacklist[$blackline] = true; if (preg_match('/' . preg_quote($blackline) . '$/i', $_REQUEST['user_template'])) { header('X-Theme-Blacklisted: ' . urlencode($blackline)); $blacklisted = true; } } } if (!$blacklisted) { $_SESSION['serendipityUseTemplate'] = $_REQUEST['user_template']; # When blacklisting occurs, the cookie to remember template selection will be removed by closing the browser. serendipity_setCookie('user_template', $_REQUEST['user_template'], false, $has_blacklist ? 0 : false); } } // If the requested template is the same as the current default template, // we will not set this variable. This is important so that templates/plugins // which detect serendipityUseTemplate can use reasonable defaults in case // template configuration options do not exist. Guess nobody understands // this explanation anyways, and who reads this stuff, heh? if ($_SESSION['serendipityUseTemplate'] == $eventData['template']) { unset($_SESSION['serendipityUseTemplate']); } if (isset($_SESSION['serendipityUseTemplate'])) { $templateInfo = serendipity_fetchTemplateInfo($_SESSION['serendipityUseTemplate']); $eventData['template'] = $_SESSION['serendipityUseTemplate']; // NOTE: Bulletproof uses diverse options, but since they are not configured by default, we cannot output fallback templates using bulletproof. So we need to use "default" for now. $eventData['template_engine'] = isset($templateInfo['engine']) ? $templateInfo['engine'] : 'default'; $serendipity['smarty_vars']['head_link_stylesheet'] = $serendipity['baseURL'] . 'serendipity.css.php?switch=' . $_REQUEST['user_template']; } return true; break; default: return false; } } else { return false; } }
/** * The meat of the plugin, called for each registered hook. * @param string event The name of the hook being called * @param mixed bag An array of configuration options for this plugin * @param mixed eventData An array containing parameters for the hook * @param mixed addData Additional hook data, if any * @return true */ function event_hook($event, &$bag, &$eventData, $addData = null) { global $serendipity; $hooks =& $bag->get('event_hooks'); if (isset($hooks[$event])) { // Update the database on first run if changed. $ver = $this->get_config('dbversion', 0); if ($ver != CATEGORYTEMPLATE_DB_VERSION) { $this->checkScheme($ver); } switch ($event) { // When changing category options, display the new extended // options, such as template, future entries, limit, and order case 'backend_category_showForm': // The $eventData is the category ID $clang = $this->fetchLang($eventData, ''); $cfuture = $this->fetchFuture($eventData, ''); $styles = serendipity_fetchTemplates(); $template = $this->fetchTemplate($eventData, ''); $hide_rss = serendipity_db_query("SELECT hide_rss FROM {$serendipity['dbPrefix']}categorytemplates AS t WHERE t.categoryid = {$eventData}", true); if ($hide_rss !== false) { $hide_rss = serendipity_db_bool($hide_rss['hide_rss']); } ?> <tr> <td valign="top"><label for="template"><?php echo SELECT_TEMPLATE; ?> </label></td> <td><input class="input_textbox" id="template" type="text" name="serendipity[cat][template]" value="<?php echo $template; ?> " /><br /> - <?php echo WORD_OR; ?> -<br /> <select name="serendipity[cat][drop_template]"> <option value=""><?php echo NONE; ?> </option> <?php foreach ($styles as $style => $path) { $templateInfo = serendipity_fetchTemplateInfo($style); ?> <option value="<?php echo function_exists('serendipity_specialchars') ? serendipity_specialchars($style) : htmlspecialchars($style, ENT_COMPAT, LANG_CHARSET); ?> " <?php echo $style == $template ? 'selected="selected"' : ''; ?> ><?php echo function_exists('serendipity_specialchars') ? serendipity_specialchars($templateInfo['name']) : htmlspecialchars($templateInfo['name'], ENT_COMPAT, LANG_CHARSET); ?> </option> <?php } ?> </select> <?php if (!empty($template)) { ?> <br /><br /><a class="serendipityPrettyButton" href="serendipity_admin.php?serendipity[adminModule]=event_display&serendipity[adminAction]=cattemplate&serendipity[catid]=<?php echo $eventData; ?> &serendipity[cat_template]=<?php echo urlencode($template); ?> "><?php echo STYLE_OPTIONS; ?> </a> <?php } ?> </td> </tr> <tr> <td colspan="2"><em><?php echo PLUGIN_CATEGORYTEMPLATES_SELECT; ?> </em></td> </tr> <!-- TODO: This does not work easily. <tr> <td><label for="language"><?php echo INSTALL_LANG; ?> </label></td> <td><select id="language" name="serendipity[cat][lang]"> <option value="default"><?php echo USE_DEFAULT; ?> </option> <?php foreach ($serendipity['languages'] as $langkey => $lang) { ?> <option value="<?php echo $lang; ?> " <?php echo $langkey == $clang ? 'selected="selected"' : ''; ?> ><?php echo function_exists('serendipity_specialchars') ? serendipity_specialchars($lang) : htmlspecialchars($lang, ENT_COMPAT, LANG_CHARSET); ?> </option> <?php } ?> </select></td> </tr> --> <tr> <td><?php echo INSTALL_SHOWFUTURE; ?> </td> <td> <input class="input_radio" type="radio" id ="futureentries_default" name="serendipity[cat][futureentries]" value="0" <?php echo empty($cfuture) || $cfuture == 0 ? 'checked="checked"' : ''; ?> /><label for="futureentries_default"><?php echo USE_DEFAULT; ?> </label><br /> <input class="input_radio" type="radio" id ="futureentries_no" name="serendipity[cat][futureentries]" value="1" <?php echo $cfuture == 1 ? 'checked="checked"' : ''; ?> /><label for="futureentries_no"><?php echo NO; ?> </label><br /> <input class="input_radio" type="radio" id ="futureentries_yes" name="serendipity[cat][futureentries]" value="2" <?php echo $cfuture == 2 ? 'checked="checked"' : ''; ?> /><label for="futureentries_yes"><?php echo YES; ?> </label> </td> </tr> <tr> <td><label for="fetchlimit"><?php echo PLUGIN_CATEGORYTEMPLATES_FETCHLIMIT; ?> </label></td> <td><input class="input_textbox" id="fetchlimit" type="text" name="serendipity[cat][fetchlimit]" value="<?php echo $this->fetchLimit($eventData, ''); ?> " /></td> </tr> <tr> <td><label for="sort_order"><?php echo SORT_ORDER; ?> </label></td> <td><input class="input_textbox" id="sort_order" type="text" name="serendipity[cat][sort_order]" value="<?php echo $this->fetchSortOrder($eventData, $this->get_config('sort_order')); ?> " /></td> </tr> <tr> <td><label for="hide_rss"><?php echo PLUGIN_CATEGORYTEMPLATES_HIDERSS; ?> </label></td> <td> <input class="input_radio" type="radio" id="hiderss_no" name="serendipity[cat][hide_rss]" value="0" <?php echo $hide_rss ? '' : 'checked="checked"'; ?> /><label for="hiderss_no"><?php echo NO; ?> </label><br /> <input class="input_radio" type="radio" id="hiderss_yes" name="serendipity[cat][hide_rss]" value="1" <?php echo $hide_rss ? 'checked="checked"' : ''; ?> /><label for="hiderss_yes"><?php echo YES; ?> </label><br /> </td> </tr> <?php if (serendipity_db_bool($this->get_config('pass'))) { ?> <tr> <td><label for="pass"><?php echo PLUGIN_CATEGORYTEMPLATES_PASS; ?> </label></td> <td><input class="input_textbox" id="pass" type="text" name="serendipity[cat][pass]" value="<?php echo $this->fetchProp($eventData, 'pass'); ?> " /></td> </tr> <?php } return true; break; // When a category is deleted, delete its custom properties // When a category is deleted, delete its custom properties case 'backend_category_delete': // $eventData is the category ID. This just deletes. $this->setProps($eventData, null, true); // Remove it from the list of template categories, too. $cidstr = $this->get_config('cat_precedence', false); // No need to modify config if no config set, or if no // templates are templatized if ($cidstr) { $cids = explode(',', $cidstr); // Why doesn't PHP have an array_remove(item)? if (in_array($eventData, $cids)) { $newcids = array(); foreach ($cids as $cid) { if ($cid != $eventData) { $newcids[] = $cid; } } $cidstr = implode(',', $newcids); $this->set_config('cat_precedence', $cidstr); } } break; // When a category is updated or added, modify its properties // When a category is updated or added, modify its properties case 'backend_category_update': case 'backend_category_addNew': $orig_tpl = $this->fetchTemplate($eventData, ''); $text_tpl = $serendipity['POST']['cat']['template']; $drop_tpl = $serendipity['POST']['cat']['drop_template']; // Default no change to template $set_tpl = $orig_tpl; // If text template changed, it takes precedence if ($text_tpl != $orig_tpl) { // (even when invalid; no checking) $set_tpl = $text_tpl; } else { if ($drop_tpl != $orig_tpl) { $set_tpl = $drop_tpl; } } $val = array('fetchlimit' => (int) $serendipity['POST']['cat']['fetchlimit'], 'template' => $set_tpl, 'categoryid' => (int) $eventData, 'lang' => $serendipity['POST']['cat']['lang'], 'futureentries' => (int) $serendipity['POST']['cat']['futureentries'], 'pass' => $serendipity['POST']['cat']['pass'], 'sort_order' => serendipity_db_escape_string($serendipity['POST']['cat']['sort_order']), 'hide_rss' => $serendipity['POST']['cat']['hide_rss']); $this->setProps($eventData, $val); // Update list of template categories, too. // // Get the list of customized category IDs, in precedence order $cidstr = $this->get_config('cat_precedence', false); // Only save the new precedence if we can actually // manually change templatized categories precedence if ($cidstr !== false) { if ($cidstr) { // If $cidstr is empty, this returns an array // with an empty string $cids = explode(',', $cidstr); } else { // For instance, set but empty $cids = array(); } // If it had a custom template just added, append it // to the list (user can change precedence later) if (!in_array($eventData, $cids) && !empty($set_tpl)) { $cids[] = $eventData; $cidstr = implode(',', $cids); $this->set_config('cat_precedence', $cidstr); } // If it had a custom template just deleted, remove it // from the list if (in_array($eventData, $cids) && empty($set_tpl)) { // Why doesn't PHP have an array_remove(item)? $newcids = array(); foreach ($cids as $cid) { if ($cid != $eventData) { $newcids[] = $cid; } } $cidstr = implode(',', $newcids); $this->set_config('cat_precedence', $cidstr); } } break; // When an entry or category is displayed, this changes the // CSS to the custom template // When an entry or category is displayed, this changes the // CSS to the custom template case 'external_plugin': $parts = explode('_', $eventData); if (!empty($parts[1])) { $param = (int) $parts[1]; } else { $param = null; } // Shouldn't this just be a string comparison? $methods = array('categorytemplate'); if (!in_array($parts[0], $methods)) { return; } $cid = (int) $parts[1]; $serendipity['template'] = $this->fetchTemplate($cid, $serendipity['template']); $css_mode = 'serendipity.css'; include_once S9Y_INCLUDE_PATH . 'serendipity.css.php'; exit; break; // When Serendipity tries to get the entries, check for // passwords // When Serendipity tries to get the entries, check for // passwords case 'frontend_fetchentries': case 'frontend_fetchentry': // Override sort order if (!empty($this->sort_order)) { $eventData['orderby'] = $this->sort_order . (!empty($eventData['orderby']) ? ',' : '') . $eventData['orderby'] . '/*categorytemplate*/'; } // Password not required on search or calendar, and we // don't do rss for them, either if (!isset($addData['source']) || ($addData['source'] == 'search' || $addData['source'] == 'calendar')) { return true; } // Password and RSS not required for installation if (defined('IN_installer') && IN_installer === true && defined('IN_upgrader') && IN_upgrader === true) { return true; } // Prepare to modify SQL $joins = array(); $conds = array(); $addkeys = array(); // Password protection SQL if (serendipity_db_bool($this->get_config('pass'))) { $conds[] = "(ctpass.pass IS NULL OR ctpass.pass = '******' OR ctpass.pass = '')"; $joins[] = "LEFT OUTER JOIN {$serendipity['dbPrefix']}categorytemplates ctpass\n ON (ec.categoryid = ctpass.categoryid)"; } // RSS hiding SQL if ($serendipity['view'] == 'feed') { $conds[] = "(e.id NOT IN (SELECT e.id FROM {$serendipity['dbPrefix']}entries AS e\n LEFT JOIN {$serendipity['dbPrefix']}entrycat AS ec ON ec.entryid = e.id\n JOIN {$serendipity['dbPrefix']}categorytemplates AS t ON ec.categoryid = t.categoryid AND hide_rss = '1'))"; /* $q = serendipity_db_query("SELECT categoryid FROM {$serendipity['dbPrefix']}categorytemplates WHERE hide_rss = 1"); if (is_array($q)) { $hidecats = array(); foreach($q as $hidden) { $hidecats[] = $hidden['categoryid']; } $hidecats = implode(';', $hidecats); } if (!empty($hidecats)) { $hide_sql = serendipity_getMultiCategoriesSQL($hidecats, true); $conds[] = $hide_sql; } */ /* $addkeys[] = "SUM(ctpass.hide_rss) as cat_hide_rss, "; // Reuse password join if possible if (count($joins) == 0) { $joins[] = "LEFT OUTER JOIN {$serendipity['dbPrefix']}categorytemplates AS ctpass ON (ec.categoryid = ctpass.categoryid)\n"; } //$conds[] = "(cat_hide_rss IS NULL OR cat_hide_rss < 1)"; //$conds[] = "(ctpass.hide_rss IS NULL OR ctpass.hide_rss = 0)"; //$conds[] = "(SUM(ctpass.hide_rss < 1))"; $havings[] = '(cat_hide_rss IS NULL OR cat_hide_rss < 1)'; */ } // Apply query additions // Select keys if (count($addkeys) > 0) { $cond = implode("\n", $addkeys); if (empty($eventData['select'])) { $eventData['addkey'] = $cond; } else { $eventData['addkey'] .= $cond; } } // Conditions if (count($conds) > 0) { $cond = implode(' AND ', $conds); if (empty($eventData['and'])) { $eventData['and'] = " WHERE {$cond} "; } else { $eventData['and'] .= " AND {$cond} "; } } // Joins if (count($joins) > 0) { $cond = implode("\n", $joins); if (empty($eventData['joins'])) { $eventData['joins'] = $cond; } else { $eventData['joins'] .= $cond; } } // Havings if (count($havings) > 0) { $cond = implode(' AND ', $havings); if (empty($eventData['having'])) { $eventData['having'] = "HAVING {$cond} "; } else { $eventData['having'] .= " AND {$cond} "; } } return true; break; // Experimental code: fetch language for entry // Experimental code: fetch language for entry case 'frontend_configure': // TODO: This does not work. The ID is not present! :-() // $cid = $this->getID(true); // $serendipity['lang'] = $this->fetchLang($cid, $serendipity['lang']); return true; break; // When the HTML is generated, apply properties // When the HTML is generated, apply properties case 'genpage': // Get the category in question $cid = $this->getID(); $fc = $this->get_config('fixcat'); if ((string) $fc === 'hard') { $fc = 'true'; } if ($cid != 'default' && serendipity_db_bool($fc)) { // Need this for category_name to be set. (?) $serendipity['GET']['category'] = $cid; header('X-FixEntry-Cat: true'); } // Reset s9y to use the category's properties $serendipity['fetchLimit'] = $this->fetchLimit($cid, $serendipity['fetchLimit']); $serendipity['showFutureEntries'] = $this->fetchFuture($cid, $serendipity['showFutureEntries']); $serendipity['template'] = $this->fetchTemplate($cid, $serendipity['template']); $this->sort_order = $this->fetchSortOrder($cid, $this->get_config('sort_order')); // Set the template options if (!$this->usesDefaultTemplate) { $serendipity['smarty_vars']['template_option'] = $serendipity['template'] . '_' . $cid; } // Check for password if ($cid != 'default' && serendipity_db_bool($this->get_config('pass')) && $this->fetchProp($cid, 'pass') != '') { if (!isset($_SERVER['PHP_AUTH_PW']) || $_SERVER['PHP_AUTH_PW'] != $this->fetchProp($cid, 'pass')) { header('WWW-Authenticate: Basic realm="' . PLUGIN_CATEGORYTEMPLATES_PASS_USER . '"'); header("HTTP/1.0 401 Unauthorized"); header('Status: 401 Unauthorized'); echo PLUGIN_CATEGORYTEMPLATES_PASS_USER; exit; } else { $this->current_pw = $_SERVER['PHP_AUTH_PW']; } } // Set the template stylesheet $serendipity['smarty_vars']['head_link_stylesheet'] = serendipity_rewriteURL('plugin/categorytemplate_' . $cid, 'baseURL', true); return true; break; // When the back end is displayed, use the custom template, too // When the back end is displayed, use the custom template, too case 'backend_sidebar_entries_event_display_cattemplate': if (empty($serendipity['GET']['cat_template'])) { $serendipity['GET']['cat_template'] = $serendipity['POST']['cat_template']; } if (empty($serendipity['GET']['catid'])) { $serendipity['GET']['catid'] = $serendipity['POST']['catid']; } $old = $serendipity['GET']['adminModule']; $serendipity['GET']['adminModule'] = 'templates'; $this->template_options($serendipity['GET']['cat_template'], $serendipity['GET']['catid']); $serendipity['GET']['adminModule'] = $old; return true; break; default: return true; break; } } else { return false; } }
$template_options->values =& $template_vars; serendipity_plugin_config($template_options, $template_vars, $serendipity['template'], $serendipity['template'], $template_options->keys, true, true, true, true, 'template', $template_config_groups); echo '</form><br />'; serendipity_plugin_api::hook_event('backend_templates_configuration_bottom', $template_config); } else { echo '<p>' . STYLE_OPTIONS_NONE . '</p>'; serendipity_plugin_api::hook_event('backend_templates_configuration_none', $template_config); } echo '<h3>' . SELECT_TEMPLATE . '</h3>'; ?> <br /> <?php $i = 0; $stack = array(); serendipity_plugin_api::hook_event('backend_templates_fetchlist', $stack); $themes = serendipity_fetchTemplates(); foreach ($themes as $theme) { $stack[$theme] = serendipity_fetchTemplateInfo($theme); } ksort($stack); foreach ($stack as $theme => $info) { $i++; /* Sorry, but we don't display engines */ if (strtolower($info['engine']) == 'yes') { continue; } $preview = ''; $preview_link = false; if (file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $theme . '/preview_fullsize.jpg')) { $preview .= '<a href="' . $serendipity['baseURL'] . $serendipity['templatePath'] . $theme . '/preview_fullsize.jpg" target="_blank">'; $preview_link = true;
/** * Fetches the list of available templates/themes/styles. * * @access public * @param string Directory to search for a template [recursive use] * @return array Sorted array of available template names */ function serendipity_fetchTemplates($dir = '') { global $serendipity; $cdir = @opendir($serendipity['serendipityPath'] . $serendipity['templatePath'] . $dir); $rv = array(); if (!$cdir) { return $rv; } while (($file = readdir($cdir)) !== false) { if (is_dir($serendipity['serendipityPath'] . $serendipity['templatePath'] . $dir . $file) && !preg_match('@^(\\.|CVS)@i', $file) && !file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $dir . $file . '/inactive.txt')) { if (file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $dir . $file . '/info.txt')) { $key = strtolower($file); if (isset($rv[$key])) { $key = $dir . $key; } $rv[$key] = $dir . $file; } else { $temp = serendipity_fetchTemplates($dir . $file . '/'); if (count($temp) > 0) { $rv = array_merge($rv, $temp); } } } } closedir($cdir); ksort($rv); return $rv; }