Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Thu, Jun 19, 1:13 PM

in-portal

Index: branches/5.2.x/core/kernel/nparser/compiler.php
===================================================================
--- branches/5.2.x/core/kernel/nparser/compiler.php (revision 14697)
+++ branches/5.2.x/core/kernel/nparser/compiler.php (revision 14698)
@@ -1,127 +1,142 @@
<?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.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class NParserCompiler extends kHelper {
var $Errors = array();
var $Templates = array();
function CompileTemplatesStep()
{
$templates = $this->Application->RecallVar('templates_to_compile');
- if (!$templates) {
+ if ( !$templates ) {
// build $templates
$templates = $this->FindTemplates();
}
else {
$templates = unserialize($templates);
}
+
$total = count($templates);
$current = $this->Application->RecallVar('current_template_to_compile');
- if (!$current) $current = 0;
+ if ( !$current ) {
+ $current = 0;
+ }
- if ($errors = $this->Application->RecallVar('compile_errors')) {
+ $errors = $this->Application->RecallVar('compile_errors');
+ if ( $errors ) {
$this->Errors = unserialize($errors);
}
kUtil::safeDefine('DBG_NPARSER_FORCE_COMPILE', 1);
$i = $current;
$this->Application->InitParser(true);
- while ($i < $total && $i < ($current + 20)) {
+
+ while ( $i < $total && $i < ($current + 20) ) {
$a_template = $templates[$i];
try {
$this->Application->Parser->CheckTemplate($a_template['module'] . '/' . $a_template['path']);
- }
- catch (ParserException $e) {
+ } catch ( ParserException $e ) {
$this->Errors[] = Array ('msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine());
}
$i++;
}
$this->Application->StoreVar('current_template_to_compile', $i);
$this->Application->StoreVar('templates_to_compile', serialize($templates));
$this->Application->StoreVar('compile_errors', serialize($this->Errors));
$res = floor(($current / $total) * 100);
- if ($res == 100 || $current >= $total) {
+ if ( $res == 100 || $current >= $total ) {
$this->Application->RemoveVar('templates_to_compile');
$this->Application->RemoveVar('current_template_to_compile');
$this->Application->Redirect($this->Application->GetVar('finish_template'));
}
+
echo $res;
}
function FindTemplates()
{
$this->Templates = Array ();
// find admin templates
foreach ($this->Application->ModuleInfo as $module => $options) {
if ($module == 'In-Portal') {
// don't check In-Portal admin templates, because it doesn't have them
continue;
}
$template_path = '/' . $options['Path'] . 'admin_templates';
$options['Path'] = $template_path;
$this->FindTemplateFiles($template_path, $options);
}
// find Front-End templates (from enabled themes only)
$sql = 'SELECT Name
FROM ' . $this->Application->getUnitOption('theme', 'TableName') . '
WHERE Enabled = 1';
$themes = $this->Conn->GetCol($sql);
$options = Array ();
foreach ($themes as $theme_name) {
$template_path = '/themes/' . $theme_name;
$options['Name'] = 'theme:' . $theme_name;
$options['Path'] = $template_path;
$this->FindTemplateFiles($template_path, $options);
}
return $this->Templates;
}
- function FindTemplateFiles($folderPath, $options)
+ /**
+ * Recursively collects all TPL file across whole installation
+ *
+ * @param string $folder_path
+ * @param Array $options
+ * @return void
+ */
+ function FindTemplateFiles($folder_path, $options)
{
// if FULL_PATH = "/" ensure, that all "/" in $folderPath are not deleted
- $reg_exp = '/^'.preg_quote(FULL_PATH, '/').'/';
- $folderPath = preg_replace($reg_exp, '', $folderPath, 1); // this make sense, since $folderPath may NOT contain FULL_PATH
+ $reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/';
+ $folder_path = preg_replace($reg_exp, '', $folder_path, 1); // this make sense, since $folderPath may NOT contain FULL_PATH
+
+ $iterator = new DirectoryIterator(FULL_PATH . $folder_path);
+ /* @var $file_info DirectoryIterator */
+
+ foreach ($iterator as $file_info) {
+ $filename = $file_info->getFilename();
+ $full_path = $file_info->getPathname();
- $fh = opendir(FULL_PATH.$folderPath);
- while (($sub_folder = readdir($fh))) {
- $full_path = FULL_PATH.$folderPath.'/'.$sub_folder;
- $base_name = basename($full_path);
- if (is_dir($full_path) && $base_name != '.' && $base_name != '..') {
+ if ( $file_info->isDir() && !$file_info->isDot() && $filename != '.svn' && $filename != 'CVS' ) {
$this->FindTemplateFiles($full_path, $options);
}
- else {
- $info = pathinfo($full_path);
- if (isset($info['extension']) && $info['extension'] == 'tpl') {
- $this->Templates[] = array('module' => mb_strtolower($options['Name']), 'path' => str_replace(FULL_PATH . $options['Path'] . '/', '', preg_replace('/\.tpl$/', '', $full_path)));
- }
+ elseif ( pathinfo($full_path, PATHINFO_EXTENSION) == 'tpl' ) {
+ $this->Templates[] = Array (
+ 'module' => mb_strtolower( $options['Name'] ),
+ 'path' => str_replace(FULL_PATH . $options['Path'] . '/', '', preg_replace('/\.tpl$/', '', $full_path))
+ );
}
}
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/helpers/themes_helper.php
===================================================================
--- branches/5.2.x/core/units/helpers/themes_helper.php (revision 14697)
+++ branches/5.2.x/core/units/helpers/themes_helper.php (revision 14698)
@@ -1,550 +1,558 @@
<?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.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kThemesHelper extends kHelper {
/**
* Where all themes are located
*
* @var string
*/
var $themesFolder = '';
/**
* List of theme names, found on system
*
* @var Array
*/
var $_themeNames = Array ();
/**
* Temporary array when all theme files from db are stored
*
* @var Array
*/
var $themeFiles = Array ();
public function __construct()
{
parent::__construct();
$this->themesFolder = FULL_PATH.'/themes';
}
/**
* Updates file system changes to database for selected theme
*
* @param string $theme_name
*
* @return mixed returns ID of created/used theme or false, if none created
*/
function refreshTheme($theme_name)
{
if (!file_exists($this->themesFolder . '/' . $theme_name)) {
// requested theme was not found on hdd
return false;
}
$id_field = $this->Application->getUnitOption('theme', 'IDField');
$table_name = $this->Application->getUnitOption('theme', 'TableName');
$sql = 'SELECT *
FROM ' . $table_name . '
WHERE Name = ' . $this->Conn->qstr($theme_name);
$theme_info = $this->Conn->GetRow($sql);
if ($theme_info) {
$theme_id = $theme_info[$id_field];
$theme_enabled = $theme_info['Enabled'];
}
else {
$theme_id = $theme_enabled = false;
}
$this->themeFiles = Array ();
if ($theme_id) {
if (!$theme_enabled) {
// don't process existing theme files, that are disabled
return $theme_id;
}
// reset found mark for every themes file (if theme is not new)
$sql = 'UPDATE '.TABLE_PREFIX.'ThemeFiles
SET FileFound = 0
WHERE ThemeId = '.$theme_id;
$this->Conn->Query($sql);
// get all theme files from db
$sql = 'SELECT FileId, CONCAT(FilePath, "/", FileName) AS FullPath
FROM '.TABLE_PREFIX.'ThemeFiles
WHERE ThemeId = '.$theme_id;
$this->themeFiles = $this->Conn->GetCol($sql, 'FullPath');
}
else {
// theme was not found in db, but found on hdd -> create new
$theme_info = Array (
'Name' => $theme_name,
'Enabled' => 0,
'Description' => $theme_name,
'PrimaryTheme' => 0,
'CacheTimeout' => 3600, // not in use right now
'StylesheetId' => 0, // not in use right now
'LanguagePackInstalled' => 0
);
$this->Conn->doInsert($theme_info, $table_name);
$theme_id = $this->Conn->getInsertID();
if (!$theme_enabled) {
// don't process newly created theme files, because they are disabled
return $theme_id;
}
}
$this->_themeNames[$theme_id] = $theme_name;
$theme_path = $this->themesFolder.'/'.$theme_name;
$this->FindThemeFiles('', $theme_path, $theme_id); // search from base theme directory
// delete file records from db, that were not found on hdd
$sql = 'DELETE FROM '.TABLE_PREFIX.'ThemeFiles
WHERE ThemeId = '.$theme_id.' AND FileFound = 0';
$this->Conn->Query($sql);
// install language packs, associated with theme (if any found and wasn't aready installed)
if (!$theme_info['LanguagePackInstalled']) {
$this->installThemeLanguagePack($theme_path);
$fields_hash = Array (
'LanguagePackInstalled' => 1,
);
$this->Conn->doUpdate($fields_hash, $table_name, $id_field . ' = ' . $theme_id);
}
$fields_hash = Array (
'TemplateAliases' => serialize( $this->getTemplateAliases($theme_id, $theme_path) ),
);
$this->Conn->doUpdate($fields_hash, $table_name, $id_field . ' = ' . $theme_id);
return $theme_id;
}
/**
* Installs module(-s) language pack for given theme
*
* @param string $theme_path
* @param string|bool $module_name
* @return void
*/
function installThemeLanguagePack($theme_path, $module_name = false)
{
if ( $module_name === false ) {
$modules = $this->Application->ModuleInfo;
}
else {
$modules = Array ($module_name => $this->Application->ModuleInfo[$module_name]);
}
$language_import_helper =& $this->Application->recallObject('LanguageImportHelper');
/* @var $language_import_helper LanguageImportHelper */
foreach ($modules as $module_name => $module_info) {
if ( $module_name == 'In-Portal' ) {
continue;
}
$lang_file = $theme_path . '/' . $module_info['TemplatePath'] . '_install/english.lang';
if ( file_exists($lang_file) ) {
$language_import_helper->performImport($lang_file, '|0|', '', LANG_SKIP_EXISTING);
}
}
}
/**
* Returns template aliases from "/_install/theme.xml" files in theme
*
* @param int $theme_id
* @param string $theme_path
* @return Array
* @access protected
*/
protected function getTemplateAliases($theme_id, $theme_path)
{
$template_aliases = Array ();
$xml_parser =& $this->Application->recallObject('kXMLHelper');
/* @var $xml_parser kXMLHelper */
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
if ( $module_name == 'In-Portal' ) {
continue;
}
$xml_file = $theme_path . '/' . $module_info['TemplatePath'] . '_install/theme.xml';
if ( file_exists($xml_file) ) {
$xml_data = file_get_contents($xml_file);
$root_node =& $xml_parser->Parse($xml_data);
if ( !is_object($root_node) || !is_a($root_node, 'kXMLNode') || !$root_node->Children ) {
// broken xml OR no aliases defined
continue;
}
$current_node =& $root_node->firstChild;
do {
$template_path = trim($current_node->Data);
$alias = '#' . $module_info['TemplatePath'] . strtolower($current_node->Name) . '#';
// remember alias in global theme mapping
$template_aliases[$alias] = $template_path;
// store alias in theme file record to use later in design dropdown
$t_parts = Array ('path' => dirname($template_path) == '.' ? ''
: '/' . dirname($template_path), 'file' => basename($template_path),);
$sql = 'UPDATE ' . TABLE_PREFIX . 'ThemeFiles
SET TemplateAlias = ' . $this->Conn->qstr($alias) . '
WHERE (ThemeId = ' . $theme_id . ') AND (FilePath = ' . $this->Conn->qstr($t_parts['path']) . ') AND (FileName = ' . $this->Conn->qstr($t_parts['file'] . '.tpl') . ')';
$this->Conn->Query($sql);
} while ( ($current_node =& $current_node->NextSibling()) );
}
}
return $template_aliases;
}
/**
* Installs given module language pack and refreshed it from all themes
*
* @param string $module_name
*/
function syncronizeModule($module_name)
{
$sql = 'SELECT `Name`, ThemeId
FROM ' . TABLE_PREFIX . 'Theme';
$themes = $this->Conn->GetCol($sql, 'ThemeId');
if (!$themes) {
return ;
}
foreach ($themes as $theme_id => $theme_name) {
$theme_path = $this->themesFolder . '/' . $theme_name;
// install language pack
$this->installThemeLanguagePack($theme_path, $module_name);
// update TemplateAliases mapping
$fields_hash = Array (
'TemplateAliases' => serialize( $this->getTemplateAliases($theme_id, $theme_path) ),
);
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'Theme', 'ThemeId = ' . $theme_id);
}
}
/**
* Searches for new templates (missing in db) in spefied folder
*
* @param string $folder_path subfolder of searchable theme
* @param string $theme_path theme path from web server root
* @param int $theme_id id of theme we are scanning
+ * @param int $auto_structure_mode
*/
function FindThemeFiles($folder_path, $theme_path, $theme_id, $auto_structure_mode = 1)
{
- $fh = opendir($theme_path.$folder_path.'/');
+ $ignore_regexp = $this->getIgnoreRegexp($theme_path . $folder_path);
- // always ingore design and element templates
- $ignore = Array ('^CVS$', '^\.svn$', '\.des\.tpl$', '\.elm\.tpl$');
+ $iterator = new DirectoryIterator($theme_path . $folder_path . '/');
+ /* @var $file_info DirectoryIterator */
- $sms_ingore = $theme_path . $folder_path . '/.smsignore';
+ foreach ($iterator as $file_info) {
+ $filename = $file_info->getFilename();
+ $auto_structure = preg_match($ignore_regexp, $filename) ? 2 : $auto_structure_mode;
+ $file_path = $folder_path . '/' . $filename; // don't pass path to theme top folder!
- if (file_exists($sms_ingore)) {
- $ignore = array_merge($ignore, file($sms_ingore));
- }
-
- while (($filename = readdir($fh))) {
- if ($filename == '.' || $filename == '..') continue;
-
- $auto_structure = $auto_structure_mode;
- foreach ($ignore as $pattern) {
- if (preg_match('/'.str_replace('/', '\\/', trim($pattern)).'/', $filename)) {
- $auto_structure = 2;
- break;
- }
+ if ( $file_info->isDir() && !$file_info->isDot() && $filename != 'CVS' && $filename != '.svn' ) {
+ $this->FindThemeFiles($file_path, $theme_path, $theme_id, $auto_structure);
}
-
- $full_path = $theme_path.$folder_path.'/'.$filename;
- if (is_dir($full_path)) {
- $this->FindThemeFiles($folder_path.'/'.$filename, $theme_path, $theme_id, $auto_structure);
- }
- elseif (substr($filename, -4) == '.tpl') {
- $file_path = $folder_path.'/'.$filename;
-
+ elseif ( pathinfo($filename, PATHINFO_EXTENSION) == 'tpl' ) {
$meta_info = $this->_getTemplateMetaInfo(trim($file_path, '/'), $theme_id);
$file_id = isset($this->themeFiles[$file_path]) ? $this->themeFiles[$file_path] : false;
$file_description = array_key_exists('desc', $meta_info) ? $meta_info['desc'] : '';
if ($file_id) {
// file was found in db & on hdd -> mark as existing
$fields_hash = Array (
'FileFound' => 1,
'Description' => $file_description,
'FileType' => $auto_structure,
'FileMetaInfo' => serialize($meta_info),
);
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'ThemeFiles', 'FileId = ' . $file_id);
}
else {
// file was found on hdd, but missing in db -> create new file record
$fields_hash = Array (
'ThemeId' => $theme_id,
'FileName' => $filename,
'FilePath' => $folder_path,
'Description' => $file_description,
'FileType' => $auto_structure, // 1 - built-in, 0 - custom (not in use right now), 2 - skipped in structure
'FileMetaInfo' => serialize($meta_info),
'FileFound' => 1,
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'ThemeFiles');
$this->themeFiles[$file_path] = $this->Conn->getInsertID();
}
// echo 'FilePath: [<strong>'.$folder_path.'</strong>]; FileName: [<strong>'.$filename.'</strong>]; IsNew: [<strong>'.($file_id > 0 ? 'NO' : 'YES').'</strong>]<br />';
}
+ }
+ }
+ /**
+ * Returns single regular expression to match all ignore patters, that are valid for given folder
+ *
+ * @param string $folder_path
+ * @return string
+ */
+ protected function getIgnoreRegexp($folder_path)
+ {
+ // always ignore design and element templates
+ $ignore = '\.des\.tpl$|\.elm\.tpl$';
+ $sms_ignore_file = $folder_path . '/.smsignore';
+
+ if ( file_exists($sms_ignore_file) ) {
+ $manual_patterns = array_map('trim', file($sms_ignore_file));
+
+ foreach ($manual_patterns as $manual_pattern) {
+ $ignore .= '|' . str_replace('/', '\\/', $manual_pattern);
+ }
}
+
+ return '/' . $ignore . '/';
}
/**
* Returns template information (name, description, path) from it's header comment
*
* @param string $template
* @param int $theme_id
* @return Array
*/
function _getTemplateMetaInfo($template, $theme_id)
{
static $init_made = false;
if (!$init_made) {
$this->Application->InitParser(true);
$init_made = true;
}
$template = 'theme:' . $this->_themeNames[$theme_id] . '/' . $template;
$template_file = $this->Application->TemplatesCache->GetRealFilename($template); // ".tpl" was added before
return $this->parseTemplateMetaInfo($template_file);
}
function parseTemplateMetaInfo($template_file)
{
if (!file_exists($template_file)) {
// when template without info it's placed in top category
return Array ();
}
$template_data = file_get_contents($template_file);
if (substr($template_data, 0, 6) == '<!--##') {
// template starts with comment in such format
/*<!--##
<NAME></NAME>
<DESC></DESC>
<SECTION>||</SECTION>
##-->*/
$comment_end = strpos($template_data, '##-->');
if ($comment_end === false) {
// badly formatted comment
return Array ();
}
$comment = trim( substr($template_data, 6, $comment_end - 6) );
if (preg_match_all('/<(NAME|DESC|SECTION)>(.*?)<\/(NAME|DESC|SECTION)>/is', $comment, $regs)) {
$ret = Array ();
foreach ($regs[1] as $param_order => $param_name) {
$ret[ strtolower($param_name) ] = trim($regs[2][$param_order]);
}
if (array_key_exists('section', $ret) && $ret['section']) {
$category_path = explode('||', $ret['section']);
$category_path = array_map('trim', $category_path);
$ret['section'] = implode('||', $category_path);
}
return $ret;
}
}
return Array ();
}
/**
* Updates file system changes to database for all themes (including new ones)
*
*/
function refreshThemes()
{
$themes_found = Array();
$skip_filenames = Array ('.', '..', 'CVS', '.svn');
$fh = opendir($this->themesFolder.'/');
while (($filename = readdir($fh))) {
if (in_array($filename, $skip_filenames)) {
continue;
}
if (is_dir($this->themesFolder.'/'.$filename)) {
$theme_id = $this->refreshTheme($filename);
if ($theme_id) {
$themes_found[] = $theme_id;
// increment serial of updated themes
$this->Application->incrementCacheSerial('theme', $theme_id);
}
}
}
$id_field = $this->Application->getUnitOption('theme', 'IDField');
$table_name = $this->Application->getUnitOption('theme', 'TableName');
// 1. only one theme found -> enable it and make primary
/*if (count($themes_found) == 1) {
$sql = 'UPDATE ' . $table_name . '
SET Enabled = 1, PrimaryTheme = 1
WHERE ' . $id_field . ' = ' . current($themes_found);
$this->Conn->Query($sql);
}*/
// 2. if none themes found -> delete all from db OR delete all except of found themes
$sql = 'SELECT '.$id_field.'
FROM '.$table_name;
if ($themes_found) {
$sql .= ' WHERE '.$id_field.' NOT IN ('.implode(',', $themes_found).')';
}
$theme_ids = $this->Conn->GetCol($sql);
$this->deleteThemes($theme_ids);
foreach ($theme_ids as $theme_id) {
// increment serial of deleted themes
$this->Application->incrementCacheSerial('theme', $theme_id);
}
$this->Application->incrementCacheSerial('theme');
$this->Application->incrementCacheSerial('theme-file');
$minify_helper =& $this->Application->recallObject('MinifyHelper');
/* @var $minify_helper MinifyHelper */
$minify_helper->delete();
}
/**
* Deletes themes with ids passed from db
*
* @param Array $theme_ids
*/
function deleteThemes($theme_ids)
{
if (!$theme_ids) {
return ;
}
$id_field = $this->Application->getUnitOption('theme', 'IDField');
$table_name = $this->Application->getUnitOption('theme', 'TableName');
$sql = 'DELETE FROM '.$table_name.'
WHERE '.$id_field.' IN ('.implode(',', $theme_ids).')';
$this->Conn->Query($sql);
$sql = 'DELETE FROM '.TABLE_PREFIX.'ThemeFiles
WHERE '.$id_field.' IN ('.implode(',', $theme_ids).')';
$this->Conn->Query($sql);
}
/**
* Returns current theme (also works in admin)
*
* @return int
*/
function getCurrentThemeId()
{
static $theme_id = null;
if (isset($theme_id)) {
return $theme_id;
}
if ($this->Application->isAdmin) {
// get theme, that user selected in catalog
$theme_id = $this->Application->RecallVar('theme_id');
if ($theme_id === false) {
// query, because "m_theme" is always empty in admin
$id_field = $this->Application->getUnitOption('theme', 'IDField');
$table_name = $this->Application->getUnitOption('theme', 'TableName');
$sql = 'SELECT ' . $id_field . '
FROM ' . $table_name . '
WHERE (PrimaryTheme = 1) AND (Enabled = 1)';
$theme_id = $this->Conn->GetOne($sql);
}
return $theme_id;
}
// use current theme, because it's available on Front-End
$theme_id = $this->Application->GetVar('m_theme');
if (!$theme_id) {
// happens in mod-rewrite mode, then requested template is not found
$theme_id = $this->Application->GetDefaultThemeId();
}
return $theme_id;
}
/**
* Returns page id based on given template
*
* @param string $template
* @param int $theme_id
* @return int
*/
function getPageByTemplate($template, $theme_id = null)
{
if (!isset($theme_id)) {
// during mod-rewrite url parsing current theme
// is not available to kHTTPQuery class, so don't use it
$theme_id = (int)$this->getCurrentThemeId();
}
$sql = 'SELECT ' . $this->Application->getUnitOption('c', 'IDField') . '
FROM ' . $this->Application->getUnitOption('c', 'TableName') . '
WHERE
(
(NamedParentPath = ' . $this->Conn->qstr('Content/' . $template) . ') OR
(`Type` = ' . PAGE_TYPE_TEMPLATE . ' AND CachedTemplate = ' . $this->Conn->qstr($template) . ')
)
AND (ThemeId = ' . $theme_id . ($theme_id > 0 ? ' OR ThemeId = 0' : '') . ')';
return $this->Conn->GetOne($sql);
}
}
\ No newline at end of file

Event Timeline