Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Sun, Feb 23, 6:28 AM

in-portal

Index: branches/5.0.x/core/units/general/helpers/mod_rewrite_helper.php
===================================================================
--- branches/5.0.x/core/units/general/helpers/mod_rewrite_helper.php (revision 12150)
+++ branches/5.0.x/core/units/general/helpers/mod_rewrite_helper.php (revision 12151)
@@ -1,587 +1,588 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
class kModRewriteHelper extends kHelper {
/**
* Holds a refererence to httpquery
*
* @var kHttpQuery
*/
var $HTTPQuery = null;
function kModRewriteHelper()
{
parent::kHelper();
$this->HTTPQuery =& $this->Application->recallObject('HTTPQuery');
}
function SetDefaultValues(&$vars)
{
$defaults = Array ('m_cat_id' => 0, 'm_cat_page' => 1, 'm_opener' => 's', 't' => 'index');
foreach ($defaults as $default_key => $default_value) {
// bug: null is never returned
if ($this->HTTPQuery->Get($default_key) == null) {
$vars[$default_key] = $default_value;
}
}
}
/**
* Gets language part from url
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
function ProcessLanguage(&$url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$res = false;
$url_part = array_shift($url_parts);
$sql = 'SELECT LanguageId
FROM ' . TABLE_PREFIX . 'Language
WHERE LOWER(PackName) = ' . $this->Conn->qstr($url_part) . ' AND Enabled = 1';
$language_id = $this->Conn->GetOne($sql);
$this->Application->Phrases = new PhrasesCache();
if ($language_id) {
$vars['m_lang'] = $language_id;
$res = true;
}
// $this->Application->VerifyLanguageId();
if (!$res) {
array_unshift($url_parts, $url_part);
}
return $res;
}
/**
* Gets theme part from url
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
function ProcessTheme(&$url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$res = false;
$url_part = array_shift($url_parts);
$sql = 'SELECT ThemeId
FROM ' . TABLE_PREFIX . 'Theme
WHERE LOWER(Name) = ' . $this->Conn->qstr($url_part) . ' AND Enabled = 1';
$theme_id = $this->Conn->GetOne($sql);
if ($theme_id) {
$vars['m_theme'] = $theme_id;
$res = true;
}
// $this->Application->VerifyThemeId(); // verify anyway - will set default if not found!!!
if (!$res) {
array_unshift($url_parts, $url_part);
}
return $res;
}
/**
* Extracts category part from url
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
function ProcessCategory($url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$res = false;
$url_part = array_shift($url_parts);
$category_id = 0;
$last_category_info = false;
$category_path = $url_part == 'content' ? '' : 'content';
do {
$category_path = trim($category_path . '/' . $url_part, '/');
// bb_<topic_id> -> forums/bb_2
if ( !preg_match('/^bb_[\d]+$/', $url_part) && preg_match('/(.*)_([\d]+)$/', $category_path, $rets) ) {
$category_path = $rets[1];
$vars['m_cat_page'] = $rets[2];
}
$sql = 'SELECT CategoryId, IsIndex, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE Status IN (1,4) AND (LOWER(NamedParentPath) = ' . $this->Conn->qstr($category_path) . ')';
$category_info = $this->Conn->GetRow($sql);
if ($category_info !== false) {
$last_category_info = $category_info;
$url_part = array_shift($url_parts);
$res = true;
}
} while ($category_info !== false && $url_part);
if ($last_category_info) {
// IsIndex = 2 is a Container-only page, meaning it should go to index-page child
if ($last_category_info['IsIndex'] == 2) {
$sql = 'SELECT CategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE ParentId = ' . $last_category_info['CategoryId'] . ' AND IsIndex = 1';
$category_info = $this->Conn->GetRow($sql);
if ($category_info) {
// when index sub-page is found use it, otherwise use container page
$last_category_info = $category_info;
}
}
// 1. Set virtual page as template, this will be replaced to physical template later in kApplication::Run.
// 2. Don't set CachedTemplate field as template here, because we will loose original page associated with it's cms blocks!
$vars['t'] = strtolower( preg_replace('/^Content\//i', '', $last_category_info['NamedParentPath']) );
$vars['m_cat_id'] = $last_category_info['CategoryId'];
$vars['is_virtual'] = true; // for template from POST, strange code there!
}
else {
$vars['m_cat_id'] = 0;
}
/*if ($url_part) {
array_unshift($url_parts, $url_part);
}*/
return $res;
}
/**
* Set's 1st page for all modules (will be used when not passed in url)
*
* @param Array $vars
* @todo this is temporary fix, until mod-rewrite helper will become category-independend
*/
function SetDefaultPages(&$vars)
{
// set module pages for all modules, since we don't know which module will need it
foreach ($this->Application->ModuleInfo as $module_name => $module_data) {
$vars[$module_data['Var'] . '_Page'] = 1;
}
}
- function _processTopic($url_parts, &$vars, $set_template = true)
+ function _processTopic(&$url_parts, &$vars, $set_template = true)
{
$sql = 'SELECT c.ParentPath, c.CategoryId
FROM ' . TABLE_PREFIX . 'Category AS c
WHERE c.CategoryId = ' . $vars['m_cat_id'];
$cat_item = $this->Conn->GetRow($sql);
if ($set_template) {
$item_template = $this->GetItemTemplate($cat_item, 'bb');
$vars['t'] = $item_template;
}
$this->Application->HandleEvent($bb_event, 'bb:ParseEnv', Array ('url_parts' => $url_parts, 'vars' => $vars));
+ $url_parts = $bb_event->getEventParam('url_parts');
$vars = $bb_event->getEventParam('vars');
return 'bb';
}
function ProcessModuleItem(&$url_parts, &$vars, $set_template = true)
{
if (!$url_parts) {
return false;
}
$item_filename = end($url_parts);
if (is_numeric($item_filename)) {
// this page, don't process here
return false;
}
if (preg_match('/^bb_[\d]+/', $item_filename)) {
// process topics separatly, because they don't use item filenames
return $this->_processTopic($url_parts, $vars, $set_template);
}
// locating the item in CategoryItems by filename to detect its ItemPrefix and its category ParentPath
$sql = 'SELECT ci.ItemResourceId, ci.ItemPrefix, c.ParentPath, ci.CategoryId
FROM ' . TABLE_PREFIX . 'CategoryItems AS ci
LEFT JOIN ' . TABLE_PREFIX . 'Category AS c ON c.CategoryId = ci.CategoryId
WHERE (ci.CategoryId = ' . $vars['m_cat_id'] . ') AND (ci.Filename = ' . $this->Conn->qstr($item_filename) . ')';
$cat_item = $this->Conn->GetRow($sql);
if ($cat_item !== false) {
// item found
$module_prefix = $cat_item['ItemPrefix'];
$item_template = $this->GetItemTemplate($cat_item, $module_prefix);
// converting ResourceId to correpsonding Item id
$module_config = $this->Application->getUnitOptions($module_prefix);
$sql = 'SELECT ' . $module_config['IDField'] . '
FROM ' . $module_config['TableName'] . '
WHERE ResourceId = ' . $cat_item['ItemResourceId'];
$item_id = $this->Conn->GetOne($sql);
array_pop($url_parts);
if ((!$set_template || $item_template) && $item_id) {
if ($set_template) {
$vars['t'] = $item_template;
}
$vars[$module_prefix . '_id'] = $item_id;
return $module_prefix;
}
}
return false;
}
/**
* Returns module item details template specified in given category custom field for given module prefix
*
* @param mixed $category
* @param string $module_prefix
* @return string
*/
function GetItemTemplate($category, $module_prefix)
{
$cache_key = serialize($category) . '_' . $module_prefix;
$cached_value = $this->Application->getCache(__CLASS__ . __FUNCTION__, $cache_key);
if ($cached_value !== false) {
return $cached_value;
}
if (!is_array($category)) {
if ($category == 0) {
$category = $this->Application->findModule('Var', $module_prefix, 'RootCat');
}
$sql = 'SELECT c.ParentPath, c.CategoryId
FROM ' . TABLE_PREFIX . 'Category AS c
WHERE c.CategoryId = ' . $category;
$category = $this->Conn->GetRow($sql);
}
$parent_path = implode(',',explode('|', substr($category['ParentPath'], 1, -1)));
// item template is stored in module' system custom field - need to get that field Id
$item_template_field_id = $this->_getItemTemplateCustomField($module_prefix);
// looking for item template through cats hierarchy sorted by parent path
$query = ' SELECT ccd.l1_cust_' . $item_template_field_id . ',
FIND_IN_SET(c.CategoryId, ' . $this->Conn->qstr($parent_path) . ') AS Ord1,
c.CategoryId, c.Name, ccd.l1_cust_' . $item_template_field_id . '
FROM ' . TABLE_PREFIX . 'Category AS c
LEFT JOIN ' . TABLE_PREFIX . 'CategoryCustomData AS ccd
ON ccd.ResourceId = c.ResourceId
WHERE c.CategoryId IN (' . $parent_path . ') AND ccd.l1_cust_' . $item_template_field_id . ' != \'\'
ORDER BY FIND_IN_SET(c.CategoryId, ' . $this->Conn->qstr($parent_path) . ') DESC';
$item_template = $this->Conn->GetOne($query);
$this->Application->setCache(__CLASS__ . __FUNCTION__, $cache_key, $item_template);
return $item_template;
}
/**
* Returns category custom field id, where given module prefix item template name is stored
*
* @param string $module_prefix
* @return int
*/
function _getItemTemplateCustomField($module_prefix)
{
$cached_value = $this->Application->getCache(__CLASS__ . __FUNCTION__, $module_prefix);
if ($cached_value !== false) {
return $cached_value;
}
$sql = 'SELECT CustomFieldId
FROM ' . TABLE_PREFIX . 'CustomField
WHERE FieldName = ' . $this->Conn->qstr($module_prefix . '_ItemTemplate');
$item_template_field_id = $this->Conn->GetOne($sql);
$this->Application->setCache(__CLASS__ . __FUNCTION__, $module_prefix, $item_template_field_id);
return $item_template_field_id;
}
function ProcessPhisycalTemplate($url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
do {
$template_path = implode('/', $url_parts);
$t_parts['path'] = dirname($template_path) == '.' ? '' : '/' . dirname($template_path);
$t_parts['file'] = basename($template_path);
$sql = 'SELECT FileId
FROM ' . TABLE_PREFIX . 'ThemeFiles
WHERE (FilePath = ' . $this->Conn->qstr($t_parts['path']) . ') AND (FileName = ' . $this->Conn->qstr($t_parts['file'] . '.tpl') . ')';
$template_found = $this->Conn->GetOne($sql);
if (!$template_found) {
array_shift($url_parts);
}
} while (!$template_found && $url_parts);
if ($template_found) {
$vars['t'] = $template_path;
return true;
}
return false;
}
/**
* Set's page (when found) to all modules
*
* @param Array $url_parts
* @param Array $vars
* @return string
*/
function ProcessPage(&$url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$page_number = end($url_parts);
if (!is_numeric($page_number)) {
return false;
}
// set module pages for all modules, since we don't know which module will need it
foreach ($this->Application->ModuleInfo as $module_name => $module_data) {
$vars[ $module_data['Var'] . '_id'] = 0;
$vars[ $module_data['Var'] . '_Page'] = $page_number;
}
array_pop($url_parts);
return true;
}
/**
* Checks if whole url_parts matches a whole In-CMS page
*
* @param array $url_parts
* @return boolean
*/
function ProcessFriendlyUrl($url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$sql = 'SELECT CategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE FriendlyURL = ' . $this->Conn->qstr(implode('/', $url_parts));
$friendly = $this->Conn->GetRow($sql);
if ($friendly) {
$vars['m_cat_id'] = $friendly['CategoryId'];
$vars['t'] = preg_replace('/^Content\//i', '', $friendly['NamedParentPath']);
return true;
}
return false;
}
function processRewriteURL()
{
$passed = Array ();
$url = $this->HTTPQuery->Get('_mod_rw_url_');
if (substr($url, -5) == '.html') {
$url = substr($url, 0, strlen($url) - 5);
}
$restored = false;
$sql = 'SELECT Data, Cached
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = "mod_rw_' . md5($url) . '"';
$cache = $this->Conn->GetRow($sql);
if (false && $cache && $cache['Cached'] > 0) {
// not used for now
$cache = unserialize($cache['Data']);
$vars = $cache['vars'];
$passed = $cache['passed'];
$restored = true;
}
else {
$passed = Array ();
$vars = $this->parseRewriteURL($url, $passed);
$cache = Array ('vars' => $vars, 'passed' => $passed);
$fields_hash = Array (
'VarName' => 'mod_rw_' . md5($url),
'Data' => serialize($cache),
'Cached' => adodb_mktime(),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
if (array_key_exists('t', $this->HTTPQuery->Post) && $this->HTTPQuery->Post['t']) {
// template from POST overrides template from URL.
$vars['t'] = $this->HTTPQuery->Post['t'];
if (isset($vars['is_virtual']) && $vars['is_virtual']) {
$vars['m_cat_id'] = 0; // this is virtual template category (for Proj-CMS)
}
}
unset($vars['is_virtual']);
}
foreach ($vars as $name => $value) {
$this->HTTPQuery->Set($name,$value);
}
// if ($restored) {
$this->InitAll();
// }
$this->HTTPQuery->finalizeParsing($passed);
}
function InitAll()
{
// $this->Application->Phrases = new PhrasesCache();
$this->Application->VerifyLanguageId();
$this->Application->Phrases->Init('phrases');
$this->Application->VerifyThemeId();
}
function parseRewriteURL($url, &$passed)
{
$sql = 'SELECT Data, Cached
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = "mod_rw_' . md5($url) . '"';
$vars = $this->Conn->GetRow($sql);
if (false && $vars && $vars['Cached'] > 0) {
// not used for now
$vars = unserialize($menu['Data']);
return $vars;
}
$vars = Array ();
$url_parts = $url ? explode('/', trim($url, '/')) : Array ();
$process_module = true;
if ($this->HTTPQuery->Get('rewrite') == 'on' || !$url_parts) {
$this->SetDefaultValues($vars);
}
if (!$url_parts) {
$this->InitAll();
$vars['t'] = $this->HTTPQuery->getDefaultTemplate('');
$passed[] = 'm';
return $vars;
}
else {
$vars['t'] = '';
}
$passed = Array ('m');
$this->ProcessLanguage($url_parts, $vars);
$this->ProcessTheme($url_parts, $vars);
if ( $this->ProcessFriendlyUrl($url_parts, $vars) ) {
// friendly urls work like exact match only!
return $vars;
}
// http://site-url/<language>/<theme>/<category>[_<category_page>]/<template>/<module_page>
// http://site-url/<language>/<theme>/<category>[_<category_page>]/<module_page> (category-based section template)
// http://site-url/<language>/<theme>/<category>[_<category_page>]/<template>/<module_item>
// http://site-url/<language>/<theme>/<category>[_<category_page>]/<module_item> (category-based detail template)
$found = Array ();
$category_found = $this->ProcessCategory($url_parts, $vars);
if ($category_found) {
$found[] = 'ProcessCategory';
}
$this->SetDefaultPages($vars);
$page_found = $this->ProcessPage($url_parts, $vars);
if ($page_found) {
$found[] = 'ProcessPage';
}
$module_prefix = $this->ProcessModuleItem($url_parts, $vars);
if ($module_prefix !== false) {
$passed[] = $module_prefix;
$found[] = 'ProcessModuleItem';
}
$template_found = $this->ProcessPhisycalTemplate($url_parts, $vars);
if ($template_found) {
$found[] = 'ProcessPhisycalTemplate';
}
if (($module_prefix === false) && in_array('ProcessCategory', $found)) {
// no item found, but category found -> module index page
/*if (!$vars['t']) {
// no template found before -> assume it's index
$vars['t'] = 'index';
}*/
foreach ($this->Application->ModuleInfo as $module_name => $info) {
// no idea what module we are talking about, so pass info form all modules
$passed[] = $info['Var'];
}
return $vars;
}
if (!$found) {
$not_found = $this->Application->ConfigValue('ErrorTemplate');
$vars['t'] = $not_found ? $not_found : 'error_notfound';
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$vars['m_cat_id'] = $themes_helper->getPageByTemplate($vars['t']);
header('HTTP/1.0 404 Not Found');
}
return $vars;
// $this->HTTPQuery->finalizeParsing($passed, $module_params);
}
}
?>
\ No newline at end of file

Event Timeline