array(), 'category' => array(), 'archives' => array(), 'static' => array(), 'search' => array(), 'author' => array(), ); var $suffix = array('post' => array('regex' => '', 'args' => '')); var $_replace = array('year' => array('reg'=>'([0-9]{4})', 'arg'=>'y='), 'monthnum' => array('reg'=>'([0-9]{2})', 'arg'=>'m='), 'day' => array('reg'=>'([0-9]{2})', 'arg'=>'d='), 'hour' => array('reg'=>'([0-9]{2})', 'arg'=>'hr='), 'minute' => array('reg'=>'([0-9]{2})', 'arg'=>'min='), 'second' => array('reg'=>'([0-9]{2})', 'arg'=>'sec='), 'postname' => array('reg'=>'([^/]+)', 'arg'=>'p='), 'post_id' => array('reg'=>'([0-9]+)', 'arg'=>'pi='), 'category' => array('reg'=>'([^/]+)', 'arg'=>'c='), 'author' => array('reg'=>'([^/]+)', 'arg'=>'u='), // not part of WP rules, but use similar structure 'archives' => array('reg' => '([0-9]{6})','arg' => 'a='), 'static' => array('reg' => '([^/]+)', 'arg' => 's='), 'search' => array('reg' => '([^/]+)', 'arg' => 'q='), ); var $_lp_option = 'lp_opt_'; var $_plugin_url = 'wp-content/plugins'; var $_plugin_dir = ''; var $_index = 'index.php'; var $_feed = 'feed.php'; var $_sitemap = 'sitemap.php'; var $setting_names = array('basedir', 'url', 'wp_url'); var $settings = array(); var $rewrite_base = '/'; var $rewrite_target = '/index.php'; function LPRewriteRules($basedir = '') { // initialization $this->_plugin_dir = str_replace('/', DIRECTORY_SEPARATOR, $this->_plugin_url); // store lightpress 'home' directory if (!empty($basedir)) $this->settings['basedir'] = $basedir; // prep settings array foreach($this->prefix as $k=>$v) $this->setting_names[] = $k . '_prefix'; foreach($this->suffix as $k=>$v) $this->setting_names[] = $k . '_suffix'; $this->setParameters(); } function setParameters($params = null) { if (!is_array($params)) $params = array(); // use setting if provided, otherwise load from db if not already set foreach($this->setting_names as $name) { if (isset($params[$name])) $this->settings[$name] = $params[$name]; elseif (!isset($this->settings[$name])) $this->settings[$name] = get_settings($this->_lp_option . $name); } // figure out rewrite base URI $this->rewrite_base = $this->getUrlPath($this->settings['url']); // figure out rewrite target URI $basedir =& $this->settings['basedir']; $pos = strpos($basedir, $this->_plugin_dir); if ($pos === false) { // not running from plugin dir, just use index file $this->rewrite_target = '/'; } else { // running as a plugin, figure out plugin dir name and construct url $this->rewrite_target = $this->_plugin_url; $path = explode(DIRECTORY_SEPARATOR, substr($basedir, $pos + strlen($this->_plugin_dir))); foreach($path as $dir) { if ($dir != '') $this->rewrite_target .= '/' . $dir; } $this->rewrite_target .= '/'; } // create regexps for context prefix/suffixes foreach($this->prefix as $name=>$val) $this->prefix[$name] = $this->getRegex($this->settings[$name . '_prefix'], $name); foreach($this->suffix as $name=>$val) $this->suffix[$name] = array('regex'=>$this->settings[$name . '_suffix'], 'args'=>array()); } function getUrlPath($url) { $url_data = parse_url($url); if (substr($url_data['path'], -1) == '/') return($url_data['path']); else return($url_data['path'] . '/'); } function getRegex($prefix, $context) { $replace =& $this->_replace; $regex = $prefix; // add context-specific names to prefix if not already there if ($context == 'post') $context = 'postname'; // default for post context $found = strpos($regex, '{' . $context . '}'); if ($found === false) { switch($context) { case 'postname': // also allow the post name (preferred) $found = strpos($regex, '{post_id}'); break; case 'archives': // can also allow year + month instead of {archives} $found = ( (strpos($regex, '{year}') !== false) && (strpos($regex, '{monthnum}') !== false) ); break; } } if (($found === false) && isset($replace[$context])) { if (substr($regex, -1) != '/') $regex .= '/'; $regex .= '{' . $context . '}'; } // get arguments in order & replace with regex $args = array(); if (preg_match_all('/{([^}]+)}/', $regex, $matches)) { foreach($matches[1] as $name) { if (isset($replace[$name])) { $args[] = $replace[$name]['arg']; // add query var to argument list $regex = str_replace('{' . $name . '}', $replace[$name]['reg'], $regex); } else { // unknown permalink verb, remove parentheses $regex = str_replace('{' . $verb . '}', $verb, $regex); } } } return (array('regex'=>$regex, 'args'=>$args)); } function generate() { // setup $base =& $this->rewrite_base; $target =& $this->rewrite_target; $index = $target . $this->_index; $feed = $target . $this->_feed; $sitemap = $target . $this->_sitemap; $rules = array(); // basic rules (enable engine, set base, check for existing files, etc.) $rules[0] = ''; $rules[] = 'RewriteEngine On'; $rules[] = 'RewriteBase ' . $base; $rules[] = 'RewriteCond %{REQUEST_FILENAME} -f [OR]'; $rules[] = 'RewriteCond %{REQUEST_FILENAME} -d'; $rules[] = 'RewriteRule ^.*$ - ' ; // finish this rule with [S=###] once we have a count of the rest $count_basic = count($rules); // basic links $rules[] = "RewriteRule ^sitemap_index.xml $sitemap [L]"; $rules[] = "RewriteRule ^trackback/([^/]+)/?$ $index?p=$1&action=trackback [QSA,L]"; $modifiers = array( array('url'=>'feed/(feed|rdf|rss|rss2|atom)(.xml)?/?', 'target'=>$feed, 'arg'=>'feed='), array('url'=>'(feed|rdf|rss|rss2|atom)(.xml)?/?', 'target'=>$feed, 'arg'=>'feed='), array('url'=>'sitemap.xml', 'target'=>$sitemap, 'arg'=>'sitemap=1'), array('url'=>'record/?([0-9]*)/?', 'target'=>$index, 'arg'=>'i='), array('url'=>'?', 'target'=>$index, 'arg'=>'') ); // context links foreach ($this->prefix as $context=>$data) { foreach($modifiers as $m) { switch($context) { // always fall through unless we want to exclude the current rule case 'post': case 'static': case 'search': case 'author': if ($m['target'] == $sitemap) break; default: $rules[] = $this->createRule($context, $m['url'], $m['target'], $m['arg']); } } } // still unclear why this rule is needed over the one above /* RewriteRule ^archives/([0-9]{4})/([0-9]{2})/sitemap.xml$ feed.php?y=$1&m=$2&feed=sitemap&sitemap=1 [QSA,L] */ // index links foreach($modifiers as $m) { if (!empty($m['url']) && ($m['url'] != '?')) $rules[] = $this->createRule('index', $m['url'], $m['target'], $m['arg']); } // feeds (WP compatibility) $rules[] = $this->createRule('', '(wp-rss.php|wp-rss2.php|wp-rdf.php)', $feed, '', '[L]'); $rules[] = $this->createRule('', 'wp-atom.php', $feed, '', '[L]'); // redirect *everything* else if we're running out of a subdir if ($target != '/') $rules[] = 'RewriteRule ^(.*) ' . $target . '$1 [QSA,L]'; // add count of rules to skip after dir/file match rule $count_rules = count($rules) - $count_basic; $rules[$count_basic - 1] .= "[S=$count_rules]"; // redirect WP feed files and all files at base url if we're running out of a subdir if ($target != '/') { // feeds (WP compatibility) $rules[] = 'RewriteRule ^(wp-rss.php|wp-rss2.php|wp-rdf.php) ' . $feed . ' [L]'; $rules[] = 'RewriteRule ^wp-atom.php ' . $feed . ' [L]'; $rules[] = 'RewriteRule ^([^/]*)$ ' . $target . '$1 [QSA,L]'; } //die ('
' . implode("\n", $rules) . '
'); if ($this->output_array) return $rules; else return implode("\n", $rules); } function createRule($context, $url, $target, $args, $type='[QSA,L]') { $rule = 'RewriteRule ^'; $arglist = array(); if (isset($this->prefix[$context])) { // context-specific prefix $rule .= $this->prefix[$context]['regex']; $arglist = array_merge($arglist, $this->prefix[$context]['args']); } if (isset($this->suffix[$context])) { // context-specific suffix $rule .= $this->suffix[$context]['regex']; $arglist = array_merge($arglist, $this->suffix[$context]['args']); } $rule .= '/' . $url; // remainder of url $rule .= '$ ' . $target; // target file $arglist = array_merge($arglist, $args); // append arguments and set pattern match values $first = true; $count = 1; foreach($arglist as $arg) { if (!empty($arg) || ($arg == '0')) { $rule .= ($first ? '?' : '&') . $arg; if (substr($arg, -1) == '=') { $rule .= '$' . $count; $count++; } $first = false; } } return($rule . ' ' . $type); } } ?>