Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Fri, Apr 18, 8:40 AM

in-portal

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: branches/5.0.x/core/units/helpers/multilanguage.php
===================================================================
--- branches/5.0.x/core/units/helpers/multilanguage.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/multilanguage.php (revision 12306)
@@ -0,0 +1,306 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ /**
+ * Performs action on multilingual fields
+ *
+ */
+ class kMultiLanguageHelper extends kHelper {
+
+ /**
+ * Maximal language id
+ *
+ * @var int
+ */
+ var $languageCount = 0;
+
+ /**
+ * Languages created in system
+ *
+ * @var Array
+ */
+ var $languagesIDs = Array ();
+
+ /**
+ * Structure of table, that is currently processed
+ *
+ * @var Array
+ */
+ var $curStructure = Array();
+
+ /**
+ * Field, to get structure information from
+ *
+ * @var string
+ */
+ var $curSourceField = false;
+
+ /**
+ * Indexes used in table of 32
+ *
+ * @var int
+ */
+ var $curIndexCount = 0;
+
+ /**
+ * Fields from config, that are currently used
+ *
+ * @var Array
+ */
+ var $curFields = Array();
+
+ function kMultiLanguageHelper()
+ {
+ parent::kHelper();
+ $this->languageCount = $this->getLanguageCount();
+ }
+
+ /**
+ * Checks if language with specified id is created
+ *
+ * @param int $language_id
+ * @return bool
+ */
+ function LanguageFound($language_id)
+ {
+ return in_array($language_id, $this->languagesIDs) || $language_id <= 5;
+ }
+
+ /**
+ * Returns language count in system (always is divisible by 5)
+ *
+ */
+ function getLanguageCount()
+ {
+ $id_field = $this->Application->getUnitOption('lang', 'IDField');
+ $table_name = $this->Application->getUnitOption('lang', 'TableName');
+
+ $this->languagesIDs = $this->Conn->GetCol('SELECT '.$id_field.' FROM '.$table_name);
+
+ $languages_count = $this->Conn->GetOne('SELECT MAX('.$id_field.') FROM '.$table_name);
+
+ return max($languages_count, 5);
+ }
+
+
+ function scanTable($mask)
+ {
+ $i = 0;
+ $fields_found = 0;
+ $fields = array_keys($this->curStructure);
+
+ foreach ($fields as $field_name) {
+ if (preg_match($mask, $field_name)) {
+ $fields_found++;
+ }
+ }
+ return $fields_found;
+ }
+
+ function readTableStructure($table_name, $refresh = false)
+ {
+// if ($refresh || !getArrayValue($structure_status, $prefix.'.'.$table_name)) {
+ $this->curStructure = $this->Conn->Query('DESCRIBE '.$table_name, 'Field');
+ $this->curIndexCount = count($this->Conn->Query('SHOW INDEXES FROM '.$table_name));
+// }
+ }
+
+ /**
+ * Creates missing multilanguage fields in table by specified prefix
+ *
+ * @param string $prefix
+ * @param bool $refresh Forces config field structure to be re-read from database
+ */
+ function createFields($prefix, $refresh = false)
+ {
+ if ($refresh && preg_match('/(.*)-cdata$/', $prefix, $regs)) {
+ // call main item config to clone cdata table
+ $this->Application->UnitConfigReader->loadConfig($regs[1]);
+ $this->Application->HandleEvent( new kEvent($prefix.':OnAfterConfigRead') );
+ }
+
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+ $this->curFields = $this->Application->getUnitOption($prefix, 'Fields');
+
+ if (!($table_name && $this->curFields) || ($table_name && !$this->Conn->TableFound($table_name))) {
+ // invalid config found or prefix not found
+ return true;
+ }
+
+ $sqls = Array();
+ $this->readTableStructure($table_name, $refresh);
+
+ foreach($this->curFields as $field_name => $field_options)
+ {
+ if (getArrayValue($field_options, 'formatter') == 'kMultiLanguage') {
+ if (isset($field_options['master_field'])) {
+ unset($this->curFields[$field_name]);
+ continue;
+ }
+
+ $this->setSourceField($field_name);
+ if ($this->languageCount > 0) {
+ // `l77_Name` VARCHAR( 255 ) NULL DEFAULT '0';
+ $field_mask = Array();
+ $field_mask['name'] = 'l%s_'.$field_name;
+ $field_mask['null'] = getArrayValue($field_options, 'not_null') ? 'NOT NULL' : 'NULL';
+
+ if ($this->curSourceField) {
+ $default_value = $this->getFieldParam('Default') != 'NULL' ? $this->Conn->qstr($this->getFieldParam('Default')) : $this->getFieldParam('Default');
+ $field_mask['type'] = $this->getFieldParam('Type');
+ }
+ else {
+ $default_value = is_null($field_options['default']) ? 'NULL' : $this->Conn->qstr($field_options['default']);
+ $field_mask['type'] = $field_options['db_type'];
+ }
+ $field_mask['default'] = 'DEFAULT '.$default_value;
+
+ if (strtoupper($field_mask['type']) == 'TEXT') {
+ // text fields in mysql doesn't have default value
+ $field_mask = $field_mask['name'].' '.$field_mask['type'].' '.$field_mask['null'];
+ }
+ else {
+ $field_mask = $field_mask['name'].' '.$field_mask['type'].' '.$field_mask['null'].' '.$field_mask['default'];
+ }
+
+ $alter_sqls = $this->generateAlterSQL($field_mask, 1, $this->languageCount);
+ if ($alter_sqls) {
+ $sqls[] = 'ALTER TABLE '.$table_name.' '.$alter_sqls;
+ }
+ }
+ }
+ }
+
+ foreach ($sqls as $sql_query) {
+ $this->Conn->Query($sql_query);
+ }
+ }
+
+ function deleteField($prefix, $custom_id)
+ {
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+ $sql = 'DESCRIBE '.$table_name.' "l%_cust_'.$custom_id.'"';
+ $fields = $this->Conn->GetCol($sql);
+
+ $sql = 'ALTER TABLE '.$table_name.' ';
+ $sql_template = 'DROP COLUMN %s, ';
+ foreach ($fields as $field_name) {
+ $sql .= sprintf($sql_template, $field_name);
+ }
+ $sql = preg_replace('/(.*), $/', '\\1', $sql);
+ $this->Conn->Query($sql);
+ }
+
+ /**
+ * Returns parameter requested of current source field
+ *
+ * @param string $param_name
+ * @return string
+ */
+ function getFieldParam($param_name)
+ {
+ return $this->curStructure[$this->curSourceField][$param_name];
+ }
+
+ /**
+ * Detects field name to create other fields from
+ *
+ * @param string $field_name
+ */
+ function setSourceField($field_name)
+ {
+ $ret = $this->scanTable('/^l[\d]+_'.preg_quote($field_name, '/').'$/');
+ if (!$ret) {
+ // no multilingual fields at all (but we have such field without language prefix)
+ $original_found = $this->scanTable('/'.preg_quote($field_name, '/').'/');
+ $this->curSourceField = $original_found ? $field_name : false;
+ }
+ else {
+ $this->curSourceField = 'l1_'.$field_name;
+ }
+ }
+
+ /**
+ * Returns ALTER statement part for adding required fields to table
+ *
+ * @param string $field_mask sql mask for creating field with correct definition (type & size)
+ * @param int $start_index add new fields starting from this index
+ * @param int $create_count create this much new multilingual field translations
+ * @return string
+ */
+ function generateAlterSQL($field_mask, $start_index, $create_count)
+ {
+ static $single_lang = null;
+ if (!isset($single_lang)) {
+ // if single language mode, then create indexes only on primary columns
+ $table_name = $this->Application->getUnitOption('lang', 'TableName');
+ $sql = 'SELECT COUNT(*)
+ FROM '.$table_name.'
+ WHERE Enabled = 1';
+ // if language count = 0, then assume it's multi language mode
+ $single_lang = $this->Conn->GetOne($sql) == 1;
+ }
+
+ $ret = '';
+ $ml_field = preg_replace('/l(.*?)_(.*?) (.*)/', '\\2', $field_mask);
+
+ $i_count = $start_index + $create_count;
+ while ($start_index < $i_count) {
+
+ if (isset($this->curStructure['l'.$start_index.'_'.$ml_field]) || (!$this->LanguageFound($start_index)) ) {
+ $start_index++;
+ continue;
+ }
+
+ $prev_index = $start_index - 1;
+ do {
+ list($prev_field,$type) = explode(' ', sprintf($field_mask, $prev_index) );
+ } while ($prev_index > 0 && !$this->LanguageFound($prev_index--));
+
+ if (substr($prev_field, 0, 3) == 'l0_') {
+ $prev_field = substr($prev_field, 3, strlen($prev_field));
+ if (!$this->curSourceField) {
+ // get field name before this one
+ $fields = array_keys($this->curFields);
+// $prev_field = key(end($this->curStructure));
+ $prev_field = $fields[array_search($prev_field, $fields) - 1];
+ if (getArrayValue($this->curFields[$prev_field], 'formatter') == 'kMultiLanguage') {
+ $prev_field = 'l'.$this->languageCount.'_'.$prev_field;
+ }
+ }
+ }
+
+ $field_expression = sprintf($field_mask, $start_index);
+ $ret .= 'ADD COLUMN '.$field_expression.' AFTER `'.$prev_field.'`, ';
+
+ if ($this->curIndexCount < 32 && ($start_index == $this->Application->GetDefaultLanguageId() || !$single_lang)) {
+ // create index for primary language column + for all others (if multiple languages installed)
+ list($field_name, $field_params) = explode(' ', $field_expression, 2);
+
+ $index_type = isset($this->curFields[$ml_field]['index_type']) ? $this->curFields[$prev_field]['index_type'] : 'string';
+
+ $ret .= $index_type == 'string' ? 'ADD INDEX (`'.$field_name.'` (5) ), ' : 'ADD INDEX (`'.$field_name.'`), ';
+ $this->curIndexCount++;
+ }
+
+ $start_index++;
+ }
+ return preg_replace('/, $/', ';', $ret);
+ }
+ }
+
+
+?>
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/multilanguage.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.15.2.1
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/clipboard_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/clipboard_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/clipboard_helper.php (revision 12306)
@@ -0,0 +1,59 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kClipboardHelper extends kHelper {
+
+ /**
+ * Set's clipboard mode
+ *
+ * @param kEvent $event
+ * @param string $mode
+ */
+ function setClipboard(&$event, $mode, $ids)
+ {
+ // clipboard = { prefix1 = { cut = {idsA}, copy = {idsB} }, ... prefixN = { cut = {idsC}, copy = {idsD} } }
+ $object = $event->getObject();
+
+ $clipboard = $this->Application->RecallVar('clipboard');
+ $clipboard = $clipboard ? unserialize($clipboard) : Array();
+
+ $prefix = $event->getPrefixSpecial();
+
+ // 1. add $ids to mode key for prefix (make sure the unique)
+ $this_mode_ids =& $clipboard[$prefix][$mode];
+ if (!is_array($this_mode_ids)) {
+ $this_mode_ids = $ids;
+ }
+ else {
+ $this_mode_ids = array_unique( array_merge($this_mode_ids, $ids) );
+ }
+
+ // 2. remove that ids from all other modes
+ $other_mode_ids =& $clipboard[$prefix][$mode == 'cut' ? 'copy' : 'cut'];
+ if (!is_array($other_mode_ids)) {
+ $other_mode_ids = Array();
+ }
+ else {
+ $other_mode_ids = array_diff($other_mode_ids, $this_mode_ids);
+ }
+
+ $this->Application->StoreVar('clipboard', serialize($clipboard));
+
+ /*// do not go up - STAY
+ $event->SetRedirectParam('opener', 's');
+ $event->SetRedirectParam('pass_events', true);*/
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/clipboard_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.2
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/spam_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/spam_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/spam_helper.php (revision 12306)
@@ -0,0 +1,144 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class SpamHelper extends kHelper {
+
+ /**
+ * Table name where spam control information is keeped
+ *
+ * @var string
+ */
+ var $TableName;
+
+ /**
+ * RecourceId field of current item
+ *
+ * @var int
+ */
+ var $ResourceId = 0;
+
+ /**
+ * Type of information to put into spam control
+ *
+ * @var string
+ */
+ var $DataType = '';
+
+ /**
+ * Default spam control record expiration
+ *
+ * @var int
+ */
+ var $Expiration = 0;
+
+ function SpamHelper()
+ {
+ parent::kHelper();
+ $this->TableName = TABLE_PREFIX.'SpamControl';
+ }
+
+ /**
+ * Initializes helper for concrete item
+ *
+ * @param int $resource_id
+ * @param string $data_type
+ * @param int $expiration
+ */
+ function InitHelper($resource_id, $data_type, $expiration)
+ {
+ $this->ResourceId = $resource_id;
+ $this->DataType = $data_type;
+
+ if (preg_match('/(.*):(.*)/', $expiration, $regs)) {
+ $delay_value = $this->Application->ConfigValue($regs[1]);
+ $delay_interval = $this->Application->ConfigValue($regs[2]);
+ $expiration = $delay_value * $delay_interval;
+ }
+
+ $this->Expiration = adodb_mktime() + $expiration;
+ }
+
+ /**
+ * Returns WHERE clause that identified each spam control record
+ *
+ * @param bool $as_array return result as array, not string
+ *
+ * @return string
+ */
+ function GetKeyClause($as_array = false)
+ {
+ $user_id = $this->Application->RecallVar('user_id');
+
+ if ($user_id == 0) {
+ $user_id = -2;
+ }
+
+ $keys = Array (
+ 'ItemResourceId' => $this->ResourceId,
+ 'IPaddress' => $_SERVER['REMOTE_ADDR'],
+ 'PortalUserId' => $user_id,
+ 'DataType' => $this->DataType,
+ );
+
+ if ($as_array) {
+ return $keys;
+ }
+
+ $ret = '';
+ foreach ($keys as $field_name => $field_value) {
+ $ret .= '('.$field_name.' = '.$this->Conn->qstr($field_value).') AND ';
+ }
+
+ return preg_replace('/(.*) AND $/', '\\1', $ret);
+ }
+
+ /**
+ * Allows to add current item in spam control
+ *
+ */
+ function AddToSpamControl()
+ {
+ $fields_hash = $this->GetKeyClause(true);
+
+ $fields_hash['Expire'] = $this->Expiration;
+ $this->Conn->doInsert($fields_hash, $this->TableName);
+ }
+
+ /**
+ * Allows to check if current item is in spam control
+ *
+ * @return bool
+ */
+ function InSpamControl()
+ {
+ $key_clause = $this->GetKeyClause();
+
+ $sql = 'SELECT Expire
+ FROM '.$this->TableName.'
+ WHERE '.$key_clause;
+ $expires = $this->Conn->GetOne($sql);
+
+ if ($expires && $expires < adodb_mktime()) {
+ // spam control record is expired
+ $sql = 'DELETE FROM '.$this->TableName.'
+ WHERE '.$key_clause;
+ $this->Conn->Query($sql);
+ return false;
+ }
+
+ return $expires ? true : false;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/spam_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/xml_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/xml_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/xml_helper.php (revision 12306)
@@ -0,0 +1,395 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kXMLHelper extends kHelper {
+
+ var $RootElement = null;
+
+ /**
+ * Enter description here...
+ *
+ * @var kXMLNode
+ */
+ var $CurrentElement = null;
+
+ var $Mode;
+
+ /**
+ * Parses XML data specified and returns root node
+ *
+ * @param string $xml
+ * @return kXMLNode
+ */
+ function &Parse($xml = null, $mode = XML_NO_TEXT_NODES)
+ {
+ $this->Mode = $mode;
+ $this->Clear(); // in case if Parse method is called more then one time
+ $xml_parser = xml_parser_create();
+ xml_set_element_handler( $xml_parser, Array(&$this, 'startElement'), Array(&$this, 'endElement') );
+ xml_set_character_data_handler( $xml_parser, Array(&$this, 'characterData') );
+ if (!xml_parse($xml_parser, $xml, 1)) {
+ $this->RootElement = new kXMLNode('ERROR', array('code'=>xml_get_error_code($xml_parser),'message'=>xml_error_string(xml_get_error_code($xml_parser))));
+ trigger_error(sprintf('XML error: %s at line %d',
+ xml_error_string(xml_get_error_code($xml_parser)),
+ xml_get_current_line_number($xml_parser)), E_USER_WARNING);
+ }
+ xml_parser_free($xml_parser);
+
+ $root_copy = $this->RootElement;
+
+ return $root_copy;
+ }
+
+ function ConvertHTMLEntities($s){
+ //build first an assoc. array with the entities we want to match
+ $table1 = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES);
+
+ $patterns = array();
+ $replacements = array();
+ //now build another assoc. array with the entities we want to replace (numeric entities)
+ foreach ($table1 as $k=>$v){
+ $patterns[] = "/$v/";
+ // $c = htmlentities($k,ENT_QUOTES,"UTF-8");
+ $replacements[] = "&#".ord($k).";";
+ }
+
+ //now perform a replacement using preg_replace
+ //each matched value in array 1 will be replaced with the corresponding value in array 2
+ $s = preg_replace($patterns,$replacements,$s);
+ return $s;
+ }
+
+ function startElement(&$Parser, &$Elem, $Attrs)
+ {
+ $parent =& $this->CurrentElement; // 1. $parent is now reference to $this->CurrentElement
+ $this->CurrentElement =& new kXMLNode($Elem, $Attrs); // 2. =& ensures, that new object won't be assigned to $parent as well (don't remove)
+ if (!isset($this->RootElement) || is_null($this->RootElement)) {
+ $this->RootElement =& $this->CurrentElement;
+ }
+ if (!is_null($parent)) {
+ $parent->AddChild($this->CurrentElement);
+ }
+ }
+
+ function characterData($Parser, $Line)
+ {
+ if ($this->Mode == XML_WITH_TEXT_NODES) {
+ $text_node = new kXMLNode('_TEXT_');
+ $text_node->AppendData($Line);
+ $this->CurrentElement->AddChild( $text_node );
+ }
+ else {
+ $this->CurrentElement->AppendData($Line);
+ }
+ }
+
+ function endElement($Parser, $Elem)
+ {
+ if ($this->Mode == XML_WITH_TEXT_NODES) {
+ /*if (count($this->CurrentElement->Children) == 1 && $this->CurrentElement->firstChild->Name == '_TEXT_') {
+ $this->CurrentElement->Children = array();
+ }*/
+ }
+ if ($this->CurrentElement->Parent != null) {
+ $this->CurrentElement =& $this->CurrentElement->Parent;
+ }
+ }
+
+ function Clear()
+ {
+ unset($this->RootElement);
+ unset($this->CurrentElement);
+ }
+ }
+
+ class kXMLNode {
+ /**
+ * Name of this node
+ *
+ * @var string
+ */
+ var $Name = null;
+
+ /**
+ * Attributes of this node
+ *
+ * @var Array
+ */
+ var $Attributes = array();
+
+ /**
+ * List of node childnodes
+ *
+ * @var Array
+ */
+ var $Children = array();
+
+ /**
+ * Node content (usually text)
+ *
+ * @var string
+ */
+ var $Data = null;
+
+ /**
+ * First child of this node
+ *
+ * @var kXMLNode
+ */
+ var $firstChild = null;
+
+ /**
+ * Last child of this node
+ *
+ * @var kXMLNode
+ */
+ var $lastChild = null;
+
+ /**
+ * Parent node
+ *
+ * @var kXMLNode
+ */
+ var $Parent = null;
+
+ /**
+ * Node position relative to other nodes of it's parent
+ *
+ * @var int
+ */
+ var $Position = 0;
+
+ /**
+ * Node identifier
+ *
+ * @var int
+ */
+ var $CRC = null;
+
+ function kXMLNode($name, $attrs = array())
+ {
+ $this->Name = strtoupper($name);
+ foreach ($attrs as $attr => $value) {
+ $this->Attributes[strtoupper($attr)] = $value;
+ }
+ $this->CRC = crc32($this->Name.join(array_keys($this->Attributes)).join(array_values($this->Attributes)));
+ }
+
+ function SetParent(&$elem)
+ {
+ $this->Parent =& $elem;
+ }
+
+ /**
+ * Adds new child to current node
+ *
+ * @param kXMLNode $a_child
+ */
+ function AddChild(&$a_child)
+ {
+ $node_count = count($this->Children);
+ $a_child->Position = $node_count;
+
+ if ($node_count == 0) {
+ $this->firstChild =& $a_child;
+ $this->lastChild =& $a_child;
+ }
+ else {
+ $this->lastChild =& $a_child;
+ }
+
+ $this->Children[] =& $a_child;
+ $a_child->SetParent($this);
+ }
+
+ /**
+ * Appends data to current node
+ *
+ * @param string $data
+ */
+ function AppendData($data)
+ {
+ $this->Data .= $data;
+ }
+
+ /**
+ * Returns child node by given path
+ *
+ * @param string $path
+ * @return kXMLNode
+ */
+ function &GetChild($path)
+ {
+ $entries = explode('/', strtoupper($path));
+ $cur = array_shift($entries);
+ if ($cur == $this->Name) $cur = array_shift($entries);
+ if (!$cur) return $this;
+ if (!isset($this->Children[$cur])) return false;
+ $left = implode('/', $entries);
+ if (!$left) return $this->Children[$cur];
+ return $this->Children[$cur]->GetChild($left);
+ }
+
+ /**
+ * Returns node value by given path
+ *
+ * @param string $path
+ * @return string
+ */
+ function GetChildValue($path)
+ {
+ $child =& $this->GetChild($path);
+ if ($child !== false) {
+ return $child->Data;
+ }
+ }
+
+ /**
+ * Returns child node by given position among it siblings
+ *
+ * @param int $position
+ * @return kXMLNode
+ */
+ function &GetChildByPosition($position)
+ {
+ if ($position < count($this->Children) ) {
+ return $this->Children[$position];
+ }
+ else {
+ $false = false;
+ return $false;
+ }
+ }
+
+ /**
+ * Recursively searches for child with given name under current node
+ *
+ * @param string $name
+ * @return kXMLNode
+ */
+ function &FindChild($name)
+ {
+ $name = strtoupper($name);
+ if ($this->Name == $name) return $this;
+ // if (isset($this->Children[$name])) return $this->Children[$name];
+ // $children = array_keys($this->Children);
+ foreach ($this->Children as $elem)
+ {
+ $child =& $elem->FindChild($name);
+ if ($child !== false)
+ {
+ return $child;
+ }
+ }
+ $false = false;
+ return $false;
+ }
+
+ /**
+ * Retruns value of given child or value of it's attribute
+ *
+ * @param string $name
+ * @param string $attr
+ * @return string
+ */
+ function FindChildValue($name, $attr=null)
+ {
+ $child =& $this->FindChild($name);
+ if ($child !== false) {
+ if (isset($attr)) {
+ return $child->Attributes[strtoupper($attr)];
+ }
+ return $child->Data;
+ }
+ }
+
+ /**
+ * Returns next node to this, false in case of end list
+ *
+ * @return kXMLNode
+ */
+ function &PrevSibling()
+ {
+ if (!is_null($this->Parent) && $this->Position > 0) {
+ $pos = $this->Position - 1;
+ do {
+ $ret =& $this->Parent->GetChildByPosition($pos--);
+ } while ($ret->Name == '_TEXT_' && $pos >= 0);
+ if ($ret->Name == '_TEXT_') $ret = false;
+ return $ret;
+ }
+ else {
+ $false = false;
+ return $false;
+ }
+ }
+
+ /**
+ * Returns next node to this, false in case of end list
+ *
+ * @return kXMLNode
+ */
+ function &NextSibling()
+ {
+ if (!is_null($this->Parent)) {
+ $pos = $this->Position + 1;
+ do {
+ $ret =& $this->Parent->GetChildByPosition($pos++);
+ } while ($pos < count($this->Parent->Children) && ($ret->Name == '_TEXT_'));
+
+ if (is_object($ret) && ($ret->Name == '_TEXT_')) {
+ $ret = false;
+ }
+ return $ret;
+ }
+ else {
+ $false = false;
+ return $false;
+ }
+ }
+ /**
+ * Reconstructs XML of the node and subnodes
+ *
+ * $param bool $content_only
+ */
+ function GetXML($content_only = false)
+ {
+ $xml = '';
+ if (!$content_only) {
+ $xml = '<'.$this->Name;
+ if (count($this->Attributes)) {
+ $xml .= ' ';
+ $att_contents = array();
+ foreach ($this->Attributes as $name => $value) {
+ $att_contents[] = $name.'="'.$value.'"';
+ }
+ $xml .= implode(' ', $att_contents);
+ }
+ $xml .= '>';
+ }
+ $xml .= $this->Data;
+ foreach ($this->Children as $node) {
+ /* @var $node kXMLNode */
+
+ $xml .= $node->GetXML($node->Name == '_TEXT_' ? true : false);
+ }
+
+ if (!$content_only) {
+ $xml .= '</'.$this->Name.'>';
+ }
+ return $xml;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/xml_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.8.2.10
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/chart_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/chart_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/chart_helper.php (revision 12306)
@@ -0,0 +1,47 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kChartHelper extends kHelper {
+
+ function kChartHelper()
+ {
+ parent::kHelper();
+ $prefix = realpath(dirname(__FILE__).'/../').'/libchart/classes/';
+ require_once $prefix.'model/Point.php';
+ require_once $prefix.'model/DataSet.php';
+ require_once $prefix.'model/XYDataSet.php';
+ require_once $prefix.'model/XYSeriesDataSet.php';
+
+ require_once $prefix.'view/primitive/Padding.php';
+ require_once $prefix.'view/primitive/Rectangle.php';
+ require_once $prefix.'view/primitive/Primitive.php';
+ require_once $prefix.'view/text/Text.php';
+ require_once $prefix.'view/color/Color.php';
+ require_once $prefix.'view/color/ColorSet.php';
+ require_once $prefix.'view/color/Palette.php';
+ require_once $prefix.'view/axis/Bound.php';
+ require_once $prefix.'view/axis/Axis.php';
+ require_once $prefix.'view/plot/Plot.php';
+ require_once $prefix.'view/caption/Caption.php';
+ require_once $prefix.'view/chart/Chart.php';
+ require_once $prefix.'view/chart/BarChart.php';
+ require_once $prefix.'view/chart/VerticalBarChart.php';
+ require_once $prefix.'view/chart/HorizontalBarChart.php';
+ require_once $prefix.'view/chart/LineChart.php';
+ require_once $prefix.'view/chart/PieChart.php';
+ }
+
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/chart_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.4.1
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/fck_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/fck_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/fck_helper.php (revision 12306)
@@ -0,0 +1,294 @@
+<?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.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+class fckFCKHelper extends kHelper {
+
+ var $Config = Array();
+
+ function fckFCKHelper()
+ {
+ parent::kHelper();
+
+ $this->Config['AllowedExtensions']['Files'] = array('jpg','gif','jpeg','png','swf','fla','jpg','gif','jpeg','png','avi','mpg','mpeg','zip','rar','arj','gz','tar','doc','pdf','ppt','rdp','swf','swt','txt','vsd','xls','csv','odt') ;
+ $this->Config['DeniedExtensions']['Files'] = array('php','asp','aspx','ascx','jsp','cfm','cfc','pl','bat','exe','dll','reg') ;
+ $this->Config['AllowedExtensions']['Images'] = array('jpg','gif','jpeg','png', 'bmp') ;
+ $this->Config['DeniedExtensions']['Images'] = array('php','asp','aspx','ascx','jsp','cfm','cfc','pl','bat','exe','dll','reg');
+ $this->Config['AllowedExtensions']['Flash'] = array('swf','fla') ;
+ $this->Config['DeniedExtensions']['Flash'] = array('php','asp','aspx','ascx','jsp','cfm','cfc','pl','bat','exe','dll','reg') ;
+ $this->Config['AllowedExtensions']['Media'] = array('asf','asx','avi','wav','wax','wma','wm','wmv','m3u','mp2v','mpg','mpeg','m1v','mp2','mp3','mpa','mpe','mpv2','mp4','mid','midi','rmi','qt','aif','aifc','aiff','mov','flv','rm','svcd','swf','vcd') ;
+ $this->Config['DeniedExtensions']['Media'] = array('php','asp','aspx','ascx','jsp','cfm','cfc','pl','bat','exe','dll','reg');
+ $this->Config['AllowedExtensions']['Documents'] = array('doc','pdf','ppt','rdp','swf','swt','txt','vsd','xls','csv','zip','odt') ;
+ $this->Config['DeniedExtensions']['Documents'] = array('php','asp','aspx','ascx','jsp','cfm','cfc','pl','bat','exe','dll','reg');
+
+ }
+
+ function CreateFolder($folder = '')
+ {
+ if (!$folder) {
+ return false;
+ }
+
+ $folderPath = WRITEABLE . '/user_files/' . $folder;
+
+ if (file_exists($folderPath) && is_dir($folderPath)) {
+ return true;
+ }
+
+ $permissions = defined('FCK_FOLDERS_PERMISSIONS') ? FCK_FOLDERS_PERMISSIONS : '0777';
+ return mkdir($folderPath); // , $permissions
+ }
+
+ function IsAllowedExtension($folder, $file_name)
+ {
+ $base_folder = $this->getBaseFolder($folder);
+ eregi("(\.[a-zA-Z0-9]{1,10})$", $file_name, $regs);
+ $ext = strtolower(ltrim($regs[1],"."));
+ if (isset($this->Config['DeniedExtensions'][$folder])) {
+ if (in_array($ext, $this->Config['DeniedExtensions'][$folder])) {
+ return false;
+ }
+ }
+ if (isset($this->Config['AllowedExtensions'][$folder])) {
+ if (!in_array($ext, $this->Config['AllowedExtensions'][$folder])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function getBaseFolder($folder)
+ {
+ $end = strpos("/", $folder);
+ if ($end) {
+ return substr($folder, 0, $end);
+ }
+ return $folder;
+ }
+
+ function ReadFolders($files_dir)
+ {
+ $aFolders = array();
+ $oCurrentFolder = opendir($files_dir) ;
+ $KernelSystemFolders = defined('KERNEL_SYSTEM_FOLDERS') ? KERNEL_SYSTEM_FOLDERS : array('icons', 'CVS', '.svn');
+ while ( $sFile = readdir( $oCurrentFolder ) )
+ {
+ if (is_dir($files_dir . $sFile ) && !in_array($sFile,$KernelSystemFolders) && $sFile != '.' && $sFile != '..') {
+ $aFolders[] = $sFile;
+ }
+ }
+ closedir( $oCurrentFolder ) ;
+ return $aFolders;
+ }
+
+
+ function ReadFiles($files_dir)
+ {
+ $aFiles = array();
+ $oCurrentFolder = opendir($files_dir) ;
+ while ( $sFile = readdir( $oCurrentFolder ) )
+ {
+ if (!is_dir($files_dir . $sFile )) {
+ $aFiles[] = $sFile;
+ }
+ }
+ closedir( $oCurrentFolder ) ;
+ return $aFiles;
+ }
+
+
+ function PrintFolders()
+ {
+ $order_by = $this->Application->GetVar('order_by');
+ $sort_by = $this->Application->GetVar('sort_by');
+ $folder = $this->Application->GetVar('folder');
+ $files_dir = WRITEABLE."/user_files/".$folder."/";
+ $aFolders = $this->ReadFolders($files_dir);
+ $ret = '';
+ $order_by = $this->Application->GetVar('order_by');
+ $sort_by = $this->Application->GetVar('sort_by');
+ natcasesort($aFolders);
+ foreach ($aFolders as $k => $v) {
+ $ret .= '<folder2 path="'.$folder."/".$v.'">'.$v.'</folder2>'."\n";
+ }
+
+ if ($sort_by == 'name' && $order_by == '_desc') {
+ $aFolders = array_reverse($aFolders);
+ }
+ foreach ($aFolders as $k => $v) {
+ $ret .= '<folder path="'.$folder."/".$v.'">'.$v.'</folder>'."\n";
+ }
+ return $ret;
+ }
+
+ function CalculateFileSize($size)
+ {
+ if ( $size > 0 ) {
+ $size = round( $size / 1024 );
+ $size = ($size < 1)? 1:$size;// round( $iFileSize / 1024 ) ;
+ }
+ return $size;
+ }
+
+ function CheckIconType($v)
+ {
+ $a_ext = Array('ai','avi','bmp','cs','dll','doc','exe','fla','gif','htm','html','jpg','js','mdb','mp3','pdf','png','ppt','rdp','swf','swt','txt','vsd','xls','xml','zip');
+
+ eregi("(\.[a-zA-Z0-9]{1,10})$", $v, $regs);
+ $ext = strtolower(ltrim($regs[1],"."));
+ if (in_array($ext, $a_ext))
+ {
+ $icon = $ext;
+ } else {
+ $icon = 'default.icon';
+ }
+ return $icon;
+ }
+
+ function GetXmlString($size,$url,$icon,$date,$file_name)
+ {
+ return '<file size="'.$size.'" url="'.$url.'" icon="'.$icon.'" date="'.$date.'">'.$file_name.'</file>'."\n";
+ }
+
+ function PrintFiles()
+ {
+ $order_by = $this->Application->GetVar('order_by');
+ $sort_by = $this->Application->GetVar('sort_by');
+
+ $folder = $this->Application->GetVar('folder');
+ $files_dir = WRITEABLE . "/user_files/" . $folder."/";
+ $files_url = BASE_PATH . WRITEBALE_BASE . "/user_files/" . $folder . "/";
+ $aFiles = $this->ReadFiles($files_dir);
+ $ret = '';
+ $date_format = "m/d/Y h:i A";
+ natcasesort($aFiles);
+ if ($sort_by == 'name' && $order_by == '_desc') {
+ $aFiles = array_reverse($aFiles,TRUE);
+ }
+
+ foreach ($aFiles as $k => $v)
+ {
+ $aFilesSize[$k] = filesize( $files_dir . $v);
+ $aFilesDate[$k] = filectime( $files_dir . $v);
+ }
+ if ($sort_by == 'name') {
+ foreach ($aFiles as $k => $file) {
+ $size = $this->CalculateFileSize($aFilesSize[$k]);
+ $date = date($date_format, $aFilesDate[$k]);
+ $icon = $this->CheckIconType($file);
+ $ret .= $this->GetXmlString($size,$files_url.$file,$icon,$date,$file);
+ }
+ }
+ if ($sort_by == 'date') {
+ asort($aFilesDate);
+ if($order_by == '_desc') {
+ $aFilesDate = array_reverse($aFilesDate,TRUE);
+ }
+ foreach ($aFilesDate as $k => $date) {
+ $size = $this->CalculateFileSize($aFilesSize[$k]);
+ $file = $aFiles[$k];
+ $date = date($date_format, $date);
+ $icon = $this->CheckIconType($file);
+ $ret .= $this->GetXmlString($size,$files_url.$file,$icon,$date,$file);
+ }
+ }
+ if ($sort_by == 'size') {
+ asort($aFilesSize);
+ if($order_by == '_desc') {
+ $aFilesSize = array_reverse($aFilesSize,TRUE);
+ }
+ foreach ($aFilesSize as $k => $size) {
+ $size = $this->CalculateFileSize($size);
+ $file = $aFiles[$k];
+ $date = date($date_format, $aFilesDate[$k]);
+ $icon = $this->CheckIconType($file);
+ $ret .= $this->GetXmlString($size,$files_url.$file,$icon,$date,$file);
+ }
+ }
+ return $ret;
+ }
+
+ function UploadFile()
+ {
+ $Extensions['Allowed']['Files'] = array('jpg','gif','jpeg','png','swf','fla','jpg','gif','jpeg','png','avi','mpg','mpeg','zip','rar','arj','gz','tar','doc','pdf','ppt','rdp','swf','swt','txt','vsd','xls','csv','odt') ;
+ $Extensions['Allowed']['Images'] = array('jpg','gif','jpeg','png', 'bmp') ;
+ $Extensions['Allowed']['Flash'] = array('swf','fla') ;
+ $Extensions['Allowed']['Media'] = array('asf','asx','avi','wav','wax','wma','wm','wmv','m3u','mp2v','mpg','mpeg','m1v','mp2','mp3','mpa','mpe','mpv2','mp4','mid','midi','rmi','qt','aif','aifc','aiff','mov','flv','rm','svcd','swf','vcd') ;
+ $Extensions['Allowed']['Documents'] = array('doc','pdf','ppt','rdp','swf','swt','txt','vsd','xls','csv','zip','odt') ;
+
+ $upload_dir = $this->Application->GetVar('upload_dir');
+ $type = explode("/",$upload_dir);
+ $type = $type[0];
+ $sServerDir = WRITEABLE."/user_files/".$upload_dir."/";
+
+ $aUpFile = $_FILES['NewFile'];
+ $sFileName = $aUpFile['name'];
+ $sOriginalFileName = $aUpFile['name'];
+ $sExtension = strtolower(substr( $sFileName, ( strrpos($sFileName, '.') + 1 ) ) );
+ $sErrorNumber = 0;
+ if ( isset( $_FILES['NewFile'] ) && !is_null( $_FILES['NewFile']['tmp_name'] ) )
+ {
+ if (in_array($sExtension,$Extensions['Allowed'][$type]))
+ {
+
+ if (!$aUpFile['error']) {
+ $iCounter = 0 ;
+ while ( true )
+ {
+ $sFilePath = $sServerDir . $sFileName ;
+ if ( is_file( $sFilePath ) )
+ {
+ $iCounter++ ;
+ $sFileName = $this->RemoveExtension( $sOriginalFileName ) . '(' . $iCounter . ').' . $sExtension ;
+ $sErrorNumber = '201' ;
+ }
+ else
+ {
+ // Turn off all error reporting.
+ error_reporting( 0 ) ;
+ // Enable error tracking to catch the error.
+ ini_set( 'track_errors', '1' ) ;
+ move_uploaded_file( $aUpFile['tmp_name'], $sFilePath ) ;
+ $sErrorMsg = $php_errormsg ;
+ // Restore the configurations.
+ ini_restore( 'track_errors' ) ;
+ ini_restore( 'error_reporting' ) ;
+
+ if ( is_file( $sFilePath ) )
+ {
+ $oldumask = umask(0) ;
+ chmod( $sFilePath, 0666 ) ;
+ umask( $oldumask ) ;
+ }
+ break ;
+ }
+ }
+ }
+ } else {
+ $sErrorNumber = '203';
+ }
+ } else {
+ $sErrorNumber = '202' ;
+ }
+ echo '<script type="text/javascript">' ;
+ echo 'window.parent.frames["frmUpload"].OnUploadCompleted(' . $sErrorNumber . ',"' . str_replace( '"', '\\"', $sFileName ) . '") ;' ;
+ echo '</script>' ;
+ }
+
+ function RemoveExtension( $fileName )
+ {
+ return substr( $fileName, 0, strrpos( $fileName, '.' ) ) ;
+ }
+}
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/fck_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.2.1
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/skin_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/skin_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/skin_helper.php (revision 12306)
@@ -0,0 +1,208 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class SkinHelper extends kHelper {
+
+ /**
+ * Allows to read some skin fields and build link to admin skin file.
+ * Will automatically compile skin file, when missing.
+ *
+ * @param Array $params
+ * @return string
+ */
+ function AdminSkinTag($params)
+ {
+ if (array_key_exists('type', $params)) {
+ // returns given field of skin
+ return $this->_getStyleField( $params['type'] );
+ }
+
+ $style_info = $this->_getStyleInfo();
+
+ if (file_exists( $this->getSkinPath() )) {
+ // returns last compiled skin
+ $ret = $this->getSkinPath(true);
+ }
+ else {
+ // search for previously compiled skin
+ $last_compiled = $this->_getLastCompiled( mb_strtolower($style_info['Name']) );
+ if ($last_compiled) {
+ // found
+ $ret = $this->getSkinPath(true, $last_compiled);
+ }
+ else {
+ // not found (try to compile on the fly)
+ $skin =& $this->Application->recallObject('skin.-item', null, Array ('skip_autoload' => true));
+ /* @var $skin kDBItem */
+
+ $skin->Load(1, 'IsPrimary');
+ $last_compiled = $this->compile($skin);
+ $ret = $last_compiled ? $this->getSkinPath(true, $last_compiled) : '';
+ }
+ }
+
+ if (array_key_exists('file_only', $params) && $params['file_only']) {
+ return $ret;
+ }
+
+ return '<link rel="stylesheet" rev="stylesheet" href="' . $ret . '" type="text/css" media="screen"/>';
+ }
+
+ /**
+ * Compiles given skin object
+ *
+ * @param kDBItem $object
+ */
+ function compile(&$object)
+ {
+ $ret = $object->GetDBField('CSS');
+ $options = $object->GetDBField('Options');
+ $options = unserialize($options);
+ $options['base_url'] = Array ('Value' => rtrim($this->Application->BaseURL(), '/'));
+
+ foreach ($options as $key => $row) {
+ $ret = str_replace('@@' . $key . '@@', $row['Value'], $ret);
+ }
+
+ $compile_ts = adodb_mktime();
+ $css_file = $this->_getStylesheetPath() . DIRECTORY_SEPARATOR . 'admin-' . mb_strtolower($object->GetDBField('Name')) . '-' . $compile_ts . '.css';
+
+ $fp = fopen($css_file, 'w');
+ if (!$fp) {
+ return false;
+ }
+
+ $prev_css = $this->_getStylesheetPath() . '/admin-' . mb_strtolower($object->GetDBField('Name')) . '-' . $object->GetDBField('LastCompiled') . '.css';
+ if (file_exists($prev_css)) {
+ unlink($prev_css);
+ }
+
+ fwrite($fp, $ret);
+ fclose($fp);
+
+ $sql = 'UPDATE ' . $object->TableName . '
+ SET LastCompiled = ' . $compile_ts . '
+ WHERE ' . $object->IDField . ' = ' . $object->GetID();
+ $this->Conn->Query($sql);
+
+ return $compile_ts;
+ }
+
+ /**
+ * Returns fields of primary admin skin
+ *
+ * @return Array
+ */
+ function _getStyleInfo()
+ {
+ static $style = null;
+
+ if (!isset($style)) {
+ $sql = 'SELECT *
+ FROM ' . TABLE_PREFIX . 'Skins
+ WHERE IsPrimary = 1';
+ $style = $this->Conn->GetRow($sql);
+ }
+
+ return $style;
+ }
+
+ /**
+ * Returns requested field value of primary admin skin
+ *
+ * @param string $field
+ * @return string
+ */
+ function _getStyleField($field)
+ {
+ if ($field == 'logo') {
+ // old style method of calling
+ $field = 'Logo';
+ }
+
+ $style_info = $this->_getStyleInfo();
+
+ if (!$style_info[$field]) {
+ return '';
+ }
+
+ $image_fields = Array ('Logo', 'LogoBottom', 'LogoLogin');
+ if (in_array($field, $image_fields)) {
+ return $this->_getStylesheetPath(true) . '/' . $style_info[$field];
+ }
+
+ return $style_info[$field];
+ }
+
+ /**
+ * Returns path, where compiled skin and it's image files are stored
+ *
+ * @param bool $url
+ * @return string
+ */
+ function _getStylesheetPath($url = false)
+ {
+ if ($url) {
+ return $this->Application->BaseURL( str_replace(DIRECTORY_SEPARATOR, '/', WRITEBALE_BASE) ) . 'user_files';
+ }
+
+ return WRITEABLE . DIRECTORY_SEPARATOR . 'user_files';
+ }
+
+ /**
+ * Returns full path to primary admin skin using given or last compiled date
+ *
+ * @param unknown_type $url
+ * @param unknown_type $compile_date
+ * @return unknown
+ */
+ function getSkinPath($url = false, $compile_date = null)
+ {
+ $style_info = $this->_getStyleInfo();
+
+ if (!isset($compile_date)) {
+ $compile_date = $style_info['LastCompiled'];
+ }
+
+ $style_name = 'admin-' . mb_strtolower($style_info['Name']) . '-' . $compile_date . '.css';
+
+ return $this->_getStylesheetPath($url) . ($url ? '/' : DIRECTORY_SEPARATOR) . $style_name;
+ }
+
+ /**
+ * Returns maximal compilation date for given skin name
+ *
+ * @param string $style_name
+ * @return int
+ */
+ function _getLastCompiled($style_name)
+ {
+ $last_compiled = 0;
+ $dh = dir($this->_getStylesheetPath() . DIRECTORY_SEPARATOR);
+
+ while (false !== ($file = $dh->read())) {
+ if ( preg_match('/admin-(.*)-([\d]+).css/', $file, $rets) ) {
+ if ($rets[1] == $style_name && $rets[2] > $last_compiled) {
+ $last_compiled = $rets[2];
+ }
+ }
+ }
+
+ $dh->close();
+
+ return $last_compiled;
+ }
+ }
\ No newline at end of file
Index: branches/5.0.x/core/units/helpers/search_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/search_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/search_helper.php (revision 12306)
@@ -0,0 +1,706 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kSearchHelper extends kHelper {
+
+
+ /**
+ * Splits search phrase into keyword using quotes,plus and minus sings and spaces as split criteria
+ *
+ * @param string $keyword
+ * @return string
+ */
+ function splitKeyword($keyword)
+ {
+ if ($this->Application->ConfigValue('CheckStopWords')) {
+ $keyword_after_remove = $this->_removeStopWords($keyword);
+ if ($keyword_after_remove) {
+ // allow to search through stop word grid
+ $keyword = $keyword_after_remove;
+ }
+ }
+
+ $quotes_re = '/([+\-]?)"(.*?)"/';
+ $no_quotes_re = '/([+\-]?)([^ ]+)/';
+
+ $quoted_kw = preg_match_all($quotes_re, $keyword, $res);
+ foreach ($res[2] as $index => $kw) $final[$kw] = $res[1][$index];
+ $keyword = preg_replace($quotes_re, '', $keyword);
+ $not_quoted_kw = preg_match_all($no_quotes_re, $keyword, $res);
+ foreach ($res[2] as $index => $kw) $final[$kw] = $res[1][$index];
+
+ return $final;
+ }
+
+ function getPositiveKeywords($keyword)
+ {
+ $keywords = $this->splitKeyword($keyword);
+
+ $ret = Array();
+ foreach ($keywords as $keyword => $sign) {
+ if ($sign == '+' || $sign == '') {
+ $ret[] = $keyword;
+ }
+ }
+ return $ret;
+ }
+
+ function buildWhereClause($keyword, $fields)
+ {
+ $keywords = $this->splitKeyword($keyword);
+
+ $normal_conditions = Array();
+ $plus_conditions = Array();
+ $minus_conditions = Array();
+
+ foreach ($keywords as $keyword => $sign) {
+ switch ($sign) {
+ case '+':
+ $plus_conditions[] = implode(' LIKE "%'.$keyword.'%" OR ', $fields).' LIKE "%'.$keyword.'%"';
+ break;
+
+ case '-':
+ foreach ($fields as $field) {
+ $condition[] = $field.' NOT LIKE "%'.$keyword.'%" OR '.$field.' IS NULL';
+ }
+ $minus_conditions[] = '('.implode(') AND (', $condition).')';
+ break;
+
+ case '':
+ $keyword = str_replace('"', '\"', $keyword);
+ $normal_conditions[] = implode(' LIKE "%'.$keyword.'%" OR ', $fields).' LIKE "%'.$keyword.'%"';
+ break;
+ }
+ }
+
+ // building where clause
+ if ($normal_conditions) {
+ $where_clause = '('.implode(') OR (', $normal_conditions).')';
+ }
+ else {
+ $where_clause = '1';
+ }
+
+ if ($plus_conditions) {
+ $where_clause = '('.$where_clause.') AND ('.implode(') AND (', $plus_conditions).')';
+ }
+
+ if ($minus_conditions) {
+ $where_clause = '('.$where_clause.') AND ('.implode(') AND (', $minus_conditions).')';
+ }
+
+ return $where_clause;
+ }
+
+ /**
+ * Returns additional information about search field
+ *
+ * @param kDBList $object
+ * @param string $field_name
+ * @return Array
+ */
+ function _getFieldInformation(&$object, $field_name)
+ {
+ $sql_filter_type = isset($object->VirtualFields[$field_name]) ? 'having' : 'where';
+ $field_type = isset($object->Fields[$field_name]['type']) ? $object->Fields[$field_name]['type'] : 'string';
+
+ if (preg_match('/(.*)\.(.*)/', $field_name, $regs)) {
+ $table_name = '`'.$regs[1].'`.'; // field from external table
+ $field_name = $regs[2];
+ }
+ elseif ($sql_filter_type == 'where') {
+ $table_name = '`'.$object->TableName.'`.'; // field from local table
+ }
+
+ $table_name = ($sql_filter_type == 'where') ? $table_name : '';
+
+ // replace wid inside table name to WID_MARK constant value
+ $is_temp_table = preg_match('/(.*)'.TABLE_PREFIX.'ses_'.$this->Application->GetSID().'(_[\d]+){0,1}_edit_(.*)/', $table_name, $regs);
+ if ($is_temp_table) {
+ $table_name = $regs[1].TABLE_PREFIX.'ses_'.EDIT_MARK.'_edit_'.$regs[3]; // edit_mark will be replaced with sid[_main_wid] in AddFilters
+ }
+
+ return Array ($field_name, $field_type, $table_name, $sql_filter_type);
+ }
+
+ /**
+ * Removes stop words from keyword
+ *
+ * @param string $keyword
+ * @return string
+ */
+ function _removeStopWords($keyword)
+ {
+ static $stop_words = Array ();
+
+ if (!$stop_words) {
+ $sql = 'SELECT StopWord
+ FROM ' . $this->Application->getUnitOption('stop-word', 'TableName') . '
+ ORDER BY LENGTH(StopWord) DESC, StopWord ASC';
+ $stop_words = $this->Conn->GetCol($sql);
+
+ foreach ($stop_words as $index => $stop_word) {
+ $stop_words[$index] = '/(^| )' . preg_quote($stop_word, '/') . '( |$)/';
+ }
+ }
+
+ $keyword = preg_replace($stop_words, ' ', $keyword);
+
+ return trim( preg_replace('/[ ]+/', ' ', $keyword) );
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ */
+ function performSearch(&$event)
+ {
+ $object =& $event->getObject();
+
+ // process search keyword
+ $search_keyword = $this->Application->GetVar( $event->getPrefixSpecial(true).'_search_keyword');
+ $this->Application->StoreVar( $event->getPrefixSpecial().'_search_keyword', $search_keyword);
+ $search_keyword = str_replace('*', '%', $search_keyword);
+
+ $custom_filter = $this->processCustomFilters($event);
+
+ if(!$search_keyword && $custom_filter === false) {
+ $this->resetSearch($event);
+ return true;
+ }
+
+ if ($search_keyword) {
+ $this->processAutomaticFilters($event, $search_keyword, $custom_filter);
+ }
+ }
+
+
+ function processAutomaticFilters(&$event, $search_keyword, $custom_filter)
+ {
+ $grid_name = $this->Application->GetVar('grid_name');
+ $grids = $this->Application->getUnitOption($event->Prefix, 'Grids');
+ $search_fields = array_keys($grids[$grid_name]['Fields']);
+
+ $search_filter = Array();
+ $object =& $event->getObject();
+
+ foreach ($search_fields as $search_field) {
+ $custom_search = isset($custom_filter[$search_field]);
+
+ $filter_data = $this->getSearchClause($object, $search_field, $search_keyword, $custom_search);
+
+ if ($filter_data) {
+ $search_filter[$search_field] = $filter_data;
+ }
+ else {
+ unset($search_filter[$search_field]);
+ }
+ }
+ $this->Application->StoreVar($event->getPrefixSpecial().'_search_filter', serialize($search_filter) );
+ }
+
+ /**
+ * Returns search clause for any particular field
+ *
+ * @param kDBList $object
+ * @param string $search_field
+ * @param string $search_keyword what we are searching (false, when building custom filter clause)
+ * @param string $custom_search already found using custom filter
+ * @return Array
+ */
+ function getSearchClause(&$object, $field_name, $search_keyword, $custom_search)
+ {
+ if (array_key_exists($field_name, $object->VirtualFields) && !array_key_exists($field_name, $object->CalculatedFields)) {
+ // Virtual field, that is shown in grid, but it doesn't have corresponding calculated field.
+ // Happens, when field value is calculated on the fly (during grid display) and it is not searchable.
+ return '';
+ }
+
+ $search_keywords = $this->splitKeyword($search_keyword);
+
+ list ($field_name, $field_type, $table_name, $sql_filter_type) = $this->_getFieldInformation($object, $field_name);
+
+ $filter_value = '';
+
+ // get field clause by formatter name and/or parameters
+ $formatter = getArrayValue($object->Fields[$field_name], 'formatter');
+ switch ($formatter) {
+ case 'kOptionsFormatter':
+ $search_keys = Array();
+
+ if ($custom_search === false) {
+ // if keywords passed through simple search filter (on each grid)
+ $use_phrases = getArrayValue($object->Fields[$field_name], 'use_phrases');
+ $field_options = $object->GetFieldOptions($field_name);
+ $multiple = array_key_exists('multiple', $field_options) && $field_options['multiple'];
+
+ foreach ($field_options['options'] as $key => $val) {
+ foreach ($search_keywords as $keyword => $sign) {
+ $pattern = '#'.$keyword.'#i';
+ if (!preg_match($pattern, $use_phrases ? $this->Application->Phrase($val) : $val)) {
+ if ($sign == '+') {
+ $filter_value = $table_name.'`'.$field_name.'` = NULL';
+ break;
+ }
+ else {
+ continue;
+ }
+ }
+
+ if ($sign == '+' || $sign == '') {
+ // don't add single quotes to found option ids when multiselect (but escape string anyway)
+ $search_keys[$key] = $multiple ? mysql_real_escape_string($key) : $this->Conn->qstr($key);
+ }
+ elseif($sign == '-') {
+ // if same value if found as exclusive too, then remove from search result
+ unset($search_keys[$key]);
+ }
+ }
+ }
+ }
+
+ if ($search_keys) {
+ if ($multiple) {
+ $filter_value = $table_name.'`'.$field_name.'` LIKE "%|' . implode('|%" OR ' . $table_name.'`'.$field_name.'` LIKE "%|', $search_keys) . '|%"';
+ }
+ else {
+ $filter_value = $table_name.'`'.$field_name.'` IN ('.implode(',', $search_keys).')';
+ }
+ }
+
+ $field_processed = true;
+ break;
+
+ case 'kDateFormatter':
+ // if date is searched using direct filter, then do nothing here, otherwise search using LIKE clause
+ $field_processed = ($custom_search !== false) ? true : false;
+ break;
+
+ default:
+ $field_processed = false;
+ break;
+ }
+
+ // if not already processed by formatter, then get clause by field type
+ if (!$field_processed && $search_keywords) {
+ switch($field_type)
+ {
+ case 'int':
+ case 'integer':
+ case 'numeric':
+ $search_keys = Array();
+ foreach ($search_keywords as $keyword => $sign) {
+ if (!is_numeric($keyword) || ($sign == '-')) continue;
+ $search_keys[] = $this->Conn->qstr($keyword);
+ }
+
+ if ($search_keys) {
+ $filter_value = $table_name.'`'.$field_name.'` IN ('.implode(',', $search_keys).')';
+ }
+ break;
+
+ case 'double':
+ case 'float':
+ case 'real':
+ $search_keys = Array();
+ foreach ($search_keywords as $keyword => $sign) {
+ $keyword = str_replace(',', '.', $keyword);
+ if (!is_numeric($keyword) || ($sign == '-')) continue;
+ $search_keys[] = 'ABS('.$table_name.'`'.$field_name.'` - '.$this->Conn->qstr($keyword).') <= 0.0001';
+ }
+
+ if ($search_keys) {
+ $filter_value = '('.implode(') OR (', $search_keys).')';
+ }
+ break;
+
+ case 'string':
+ $filter_value = $this->buildWhereClause($search_keyword, Array($table_name.'`'.$field_name.'`'));
+ break;
+ }
+ }
+
+ if ($filter_value) {
+ return Array('type' => $sql_filter_type, 'value' => $filter_value);
+ }
+
+ return false;
+ }
+
+ /**
+ * Processes custom filters from submit
+ *
+ * @param KEvent $event
+ * @return bool
+ */
+ function processCustomFilters(&$event)
+ {
+ $grid_name = $this->Application->GetVar('grid_name');
+
+ // update "custom filter" with values from submit: begin
+ $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
+ $custom_filters = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_custom_filter.'.$view_name/*, ALLOW_DEFAULT_SETTINGS*/);
+ if ($custom_filters) {
+ $custom_filters = unserialize($custom_filters);
+ $custom_filter = isset($custom_filters[$grid_name]) ? $custom_filters[$grid_name] : Array ();
+ }
+ else {
+ $custom_filter = Array ();
+ }
+
+ // submit format custom_filters[prefix_special][field]
+ $submit_filters = $this->Application->GetVar('custom_filters');
+ if ($submit_filters) {
+ $submit_filters = getArrayValue($submit_filters, $event->getPrefixSpecial(), $grid_name);
+ if ($submit_filters) {
+ foreach ($submit_filters as $field_name => $field_options) {
+ list ($filter_type, $field_value) = each($field_options);
+ $is_empty = strlen(is_array($field_value) ? implode('', $field_value) : $field_value) == 0;
+ if ($is_empty) {
+ if (isset($custom_filter[$field_name])) {
+ // use isset, because non-existing key will cause "php notice"!
+ unset($custom_filter[$field_name][$filter_type]); // remove filter
+
+ if (!$custom_filter[$field_name]) {
+ // if no filters left for field, then delete record at all
+ unset($custom_filter[$field_name]);
+ }
+ }
+ }
+ else {
+ $custom_filter[$field_name][$filter_type]['submit_value'] = $field_value;
+ }
+ }
+ }
+ }
+
+ if ($custom_filter) {
+ $custom_filters[$grid_name] = $custom_filter;
+ }
+ else {
+ unset($custom_filters[$grid_name]);
+ }
+ // update "custom filter" with values from submit: end
+
+ if (!$custom_filter) {
+ // in case when no filters specified, there are nothing to process
+ $this->Application->StorePersistentVar($event->getPrefixSpecial().'_custom_filter.'.$view_name, serialize($custom_filters) );
+ return false;
+ }
+
+ $object =& $event->getObject(); // don't recall it each time in getCustomFilterSearchClause
+ $grid_info = $this->Application->getUnitOption($event->Prefix.'.'.$grid_name, 'Grids');
+ foreach ($custom_filter as $field_name => $field_options) {
+ list ($filter_type, $field_options) = each($field_options);
+ $field_options['grid_options'] = $grid_info['Fields'][$field_name];
+ $field_options = $this->getCustomFilterSearchClause($object, $field_name, $filter_type, $field_options);
+ if ($field_options['value']) {
+ unset($field_options['grid_options']);
+ $custom_filter[$field_name][$filter_type] = $field_options;
+ }
+ }
+
+ $custom_filters[$grid_name] = $custom_filter;
+ $this->Application->StorePersistentVar($event->getPrefixSpecial().'_custom_filter.'.$view_name, serialize($custom_filters) );
+ return $custom_filter;
+ }
+
+ /**
+ * Checks, that range filters "To" part is defined for given grid
+ *
+ * @param string $prefix_special
+ * @param string $grid_name
+ * @return bool
+ */
+ function rangeFiltersUsed($prefix_special, $grid_name)
+ {
+ static $cache = Array ();
+ $cache_key = $prefix_special . $grid_name;
+
+ if (array_key_exists($cache_key, $cache)) {
+ return $cache[$cache_key];
+ }
+
+ $view_name = $this->Application->RecallVar($prefix_special . '_current_view');
+ $custom_filters = $this->Application->RecallPersistentVar($prefix_special . '_custom_filter.' . $view_name/*, ALLOW_DEFAULT_SETTINGS*/);
+ if (!$custom_filters) {
+ // filters not defined for given prefix
+ $cache[$cache_key] = false;
+ return false;
+ }
+
+ $custom_filters = unserialize($custom_filters);
+ if (!array_key_exists($grid_name, $custom_filters)) {
+ // filters not defined for given grid
+ $cache[$cache_key] = false;
+ return false;
+ }
+
+ $range_filter_defined = false;
+
+ $custom_filter = $custom_filters[$grid_name];
+ foreach ($custom_filter as $field_name => $field_options) {
+ list ($filter_type, $field_options) = each($field_options);
+
+ if (strpos($filter_type, 'range') === false) {
+ continue;
+ }
+
+ $to_value = (string)$field_options['submit_value']['to'];
+ if ($to_value !== '') {
+ $range_filter_defined = true;
+ break;
+ }
+ }
+
+ $cache[$cache_key] = $range_filter_defined;
+ return $range_filter_defined;
+ }
+
+ /**
+ * Return numeric range filter value + checking that it's number
+ *
+ * @param Array $value array containing range filter value
+ * @return unknown
+ */
+ function getRangeValue($value)
+ {
+ return strlen($value) && is_numeric($value) ? $this->Conn->qstr($value) : false;
+ }
+
+ function getCustomFilterSearchClause(&$object, $field_name, $filter_type, $field_options)
+ {
+ // this is usually used for mutlilingual fields and date fields
+ if (isset($field_options['grid_options']['sort_field'])) {
+ $field_name = $field_options['grid_options']['sort_field'];
+ }
+ list ($field_name, $field_type, $table_name, $sql_filter_type) = $this->_getFieldInformation($object, $field_name);
+
+ $filter_value = '';
+
+ switch ($filter_type) {
+ case 'range':
+ $from = $this->getRangeValue($field_options['submit_value']['from']);
+ $to = $this->getRangeValue($field_options['submit_value']['to']);
+
+ if ($from !== false && $to !== false) {
+ // add range filter
+ $filter_value = $table_name.'`'.$field_name.'` >= '.$from.' AND '.$table_name.'`'.$field_name.'` <= '.$to;
+ }
+ elseif ($from !== false) {
+ // add equals filter on $from
+ $filter_value = $table_name.'`'.$field_name.'` = '.$from;
+ }
+ elseif ($to !== false) {
+ // add equals filter on $to
+ $filter_value = $table_name.'`'.$field_name.'` = '.$to;
+ }
+ break;
+
+ case 'float_range':
+ // MySQL can't compare values in "float" type columns using "=" operator
+ $from = $this->getRangeValue($field_options['submit_value']['from']);
+ $to = $this->getRangeValue($field_options['submit_value']['to']);
+
+ if ($from !== false && $to !== false) {
+ // add range filter
+ $filter_value = $table_name.'`'.$field_name.'` >= '.$from.' AND '.$table_name.'`'.$field_name.'` <= '.$to;
+ }
+ elseif ($from !== false) {
+ // add equals filter on $from
+ $filter_value = 'ABS('.$table_name.'`'.$field_name.'` - '.$from.') <= 0.0001';
+ }
+ elseif ($to !== false) {
+ // add equals filter on $to
+ $filter_value = 'ABS('.$table_name.'`'.$field_name.'` - '.$to.') <= 0.0001';
+ }
+ break;
+
+ case 'date_range':
+ $from = $this->processRangeField($object, $field_name, $field_options['submit_value'], 'from');
+ $to = $this->processRangeField($object, $field_name, $field_options['submit_value'], 'to');
+
+ $day_seconds = 23 * 60 * 60 + 59 * 60 + 59;
+ if ($from !== false && $to === false) {
+ $from = strtotime(date('Y-m-d', $from) . ' 00:00:00', $from); // reset to morning
+ $to = $from + $day_seconds;
+ }
+ elseif ($from === false && $to !== false) {
+ $to = strtotime(date('Y-m-d', $to) . ' 23:59:59', $to); // reset to evening
+ $from = $to - $day_seconds;
+ }
+
+ if ($from !== false && $to !== false) {
+ $filter_value = $table_name.'`'.$field_name.'` >= '.$from.' AND '.$table_name.'`'.$field_name.'` <= '.$to;
+ }
+ break;
+
+ case 'equals':
+ case 'options':
+ $field_value = strlen($field_options['submit_value']) ? $this->Conn->qstr($field_options['submit_value']) : false;
+ if ($field_value) {
+ $filter_value = $table_name.'`'.$field_name.'` = '.$field_value;
+ }
+ break;
+
+ case 'picker':
+ $field_value = strlen($field_options['submit_value']) ? $field_options['submit_value'] : false;
+ if ($field_value) {
+ $filter_value = $table_name.'`'.$field_name.'` LIKE "%|'.$field_value.'|%"';
+ }
+ break;
+
+ case 'like':
+ $filter_value = $this->buildWhereClause($field_options['submit_value'], Array($table_name.'`'.$field_name.'`'));
+ break;
+
+ default:
+ break;
+ }
+
+ $field_options['sql_filter_type'] = $sql_filter_type;
+ $field_options['value'] = $filter_value;
+
+ return $field_options;
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kdbItem $object
+ * @param string $search_field
+ * @param string $value
+ * @param string $type
+ */
+ function processRangeField(&$object, $search_field, $value, $type)
+ {
+ if (!strlen($value[$type])) {
+ return false;
+ }
+
+ $options = $object->GetFieldOptions($search_field);
+ $dt_separator = array_key_exists('date_time_separator', $options) ? $options['date_time_separator'] : ' ';
+ $value[$type] = trim($value[$type], $dt_separator); // trim any
+
+ $tmp_value = explode($dt_separator, $value[$type], 2);
+ if (count($tmp_value) == 1) {
+ $time_format = $this->_getInputTimeFormat($options);
+ if ($time_format) {
+ // time is missing, but time format available -> guess time and add to date
+ $time = ($type == 'from') ? adodb_mktime(0, 0, 0) : adodb_mktime(23, 59, 59);
+ $time = adodb_date($time_format, $time);
+ $value[$type] .= $dt_separator . $time;
+ }
+ }
+
+ $formatter =& $this->Application->recallObject($object->Fields[$search_field]['formatter']);
+
+ $value_ts = $formatter->Parse($value[$type], $search_field, $object);
+ $pseudo = getArrayValue($object->FieldErrors, $search_field, 'pseudo');
+ if ($pseudo) {
+ unset($object->FieldErrors[$search_field]); // remove error!
+ // invalid format -> ignore this date in search
+ return false;
+ }
+ return $value_ts;
+ }
+
+ /**
+ * Returns InputTimeFormat using given field options
+ *
+ * @param Array $field_options
+ * @return string
+ */
+ function _getInputTimeFormat($field_options)
+ {
+ if (array_key_exists('input_time_format', $field_options)) {
+ return $field_options['input_time_format'];
+ }
+
+ $lang_current =& $this->Application->recallObject('lang.current');
+ return $lang_current->GetDBField('InputTimeFormat');
+ }
+
+ /**
+ * Resets current search
+ *
+ * @param kEvent $event
+ */
+ function resetSearch(&$event)
+ {
+ $this->Application->RemoveVar($event->getPrefixSpecial().'_search_filter');
+ $this->Application->RemoveVar($event->getPrefixSpecial().'_search_keyword');
+
+ $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
+ $this->Application->RemovePersistentVar($event->getPrefixSpecial().'_custom_filter.'.$view_name);
+ }
+
+ /**
+ * Creates filters based on "types" & "except" parameters from PrintList
+ *
+ * @param kEvent $event
+ * @param Array $type_clauses
+ * @param string $types
+ * @param string $except_types
+ */
+ function SetComplexFilter(&$event, &$type_clauses, $types, $except_types)
+ {
+ $includes_or_filter =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_OR);
+ $excepts_and_filter =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_AND);
+
+ $includes_or_filter_h =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_OR);
+ $excepts_and_filter_h =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_AND);
+
+ if ($types) {
+ $types = explode(',', $types);
+ foreach ($types as $type) {
+ $type = trim($type);
+
+ if (isset($type_clauses[$type])) {
+ if ($type_clauses[$type]['having_filter']) {
+ $includes_or_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['include']);
+ } else {
+ $includes_or_filter->addFilter('filter_'.$type, $type_clauses[$type]['include']);
+ }
+ }
+ }
+ }
+
+ if ($except_types) {
+ $except_types = explode(',', $except_types);
+ foreach ($except_types as $type) {
+ $type = trim($type);
+
+ if (isset($type_clauses[$type])) {
+ if ($type_clauses[$type]['having_filter']) {
+ $excepts_and_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['except']);
+ } else {
+ $excepts_and_filter->addFilter('filter_'.$type, $type_clauses[$type]['except']);
+ }
+ }
+ }
+ }
+
+ $object =& $event->getObject();
+
+ $object->addFilter('includes_filter', $includes_or_filter);
+ $object->addFilter('excepts_filter', $excepts_and_filter);
+
+ $object->addFilter('includes_filter_h', $includes_or_filter_h, HAVING_FILTER);
+ $object->addFilter('excepts_filter_h', $excepts_and_filter_h, HAVING_FILTER);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/search_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.10.2.8
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/curl_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/curl_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/curl_helper.php (revision 12306)
@@ -0,0 +1,265 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kCurlHelper extends kHelper {
+
+ /**
+ * Connection to host
+ *
+ * @var resource
+ */
+ var $connectionID = null;
+
+ /**
+ * Pointer to opened log file
+ *
+ * @var resource
+ */
+ var $logFilePointer = null;
+
+ /**
+ * Responce waiting timeout
+ *
+ * @var int
+ */
+ var $timeout = 90;
+
+ /**
+ * Follow to url, if redirect received insted of document (only works when open_basedir and safe mode is off)
+ *
+ * @var bool
+ */
+ var $followLocation = false;
+
+ /**
+ * Last responce received by Curl
+ *
+ * @var string
+ */
+ var $lastRespoce = '';
+
+ /**
+ * Last error code
+ *
+ * @var int
+ */
+ var $lastErrorCode = 0;
+
+ /**
+ * Last error message
+ *
+ * @var string
+ */
+ var $lastErrorMsg = '';
+
+ /**
+ * Most recent HTTP responce code received
+ *
+ * @var int
+ */
+ var $lastHTTPCode = 0;
+
+ /**
+ * POST data to be sent using curl
+ *
+ * @var string
+ */
+ var $postData = '';
+
+ var $requestHeaders = Array ();
+
+ var $responceHeaders = Array ();
+
+ var $options = Array ();
+
+ /**
+ * Indicates debug mode status
+ *
+ * @var bool
+ */
+ var $debugMode = false;
+
+ function kCurlHelper()
+ {
+ parent::kHelper();
+
+ $this->debugMode = $this->Application->isDebugMode(false) && constOn('DBG_CURL');
+ }
+
+ /**
+ * Reset connection settings (not results) after connection was closed
+ *
+ */
+ function _resetSettings()
+ {
+ $this->timeout = 90;
+ $this->followLocation = false;
+ $this->postData = '';
+ $this->requestHeaders = Array ();
+ $this->options = Array ();
+ }
+
+ function setOptions($options_hash)
+ {
+ $this->options = array_merge_recursive2($this->options, $options_hash);
+ }
+
+ function prepareOptions()
+ {
+ $default_options = Array (
+ // customizable options
+ CURLOPT_FOLLOWLOCATION => $this->followLocation ? 1 : 0,
+ CURLOPT_TIMEOUT => $this->timeout,
+
+ // hardcoded options
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_REFERER => PROTOCOL.SERVER_NAME,
+ CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
+ );
+
+ if ($this->requestHeaders) {
+ $default_options[CURLOPT_HTTPHEADER] = $this->prepareHeaders();
+ }
+
+ // if we have post data, then POST else use GET method instead
+ if ($this->postData) {
+ $default_options[CURLOPT_POST] = 1;
+ $default_options[CURLOPT_POSTFIELDS] = $this->postData;
+ }
+
+// $default_options[CURLOPT_HEADERFUNCTION] = Array(&$this, 'ParseHeader');
+
+ $user_options = $this->options; // backup options, that user set directly
+ $this->setOptions($default_options);
+ $this->setOptions($user_options);
+ $this->applyOptions();
+ }
+
+ function applyOptions()
+ {
+ foreach ($this->options as $option_name => $option_value) {
+ curl_setopt($this->connectionID, $option_name, $option_value);
+ }
+ }
+
+ function ParseHeader(&$ch, $header)
+ {
+ $this->responceHeaders[] = $header;
+ return strlen($header);
+ }
+
+ /**
+ * Sets POST data for next query
+ *
+ * @param mixed $post_data Array or string
+ */
+ function SetPostData($post_data)
+ {
+ if (is_array($post_data)) {
+ $params_str = '';
+ foreach ($post_data as $key => $value) {
+ $params_str .= $key.'='.urlencode($value).'&';
+ }
+ $post_data = $params_str;
+ }
+
+ $this->postData = $post_data;
+ }
+
+ function SetHeaders($headers)
+ {
+ $this->requestHeaders = array_merge_recursive2($this->requestHeaders, $headers);
+ }
+
+ function SetHeader($name, $value)
+ {
+ $this->requestHeaders[$name] = $value;
+ }
+
+ /**
+ * Returns compiled header to be used by curl
+ *
+ * @return Array
+ */
+ function prepareHeaders()
+ {
+ $ret = Array ();
+ foreach ($this->requestHeaders as $header_name => $header_value) {
+ $ret[] = $header_name.': '.$header_value;
+ }
+ return $ret;
+ }
+
+ function Send($url, $close_connection = true)
+ {
+ $this->connectionID = curl_init($url);
+
+ if ($this->debugMode) {
+ safeDefine('DBG_CURL_LOGFILE', '/curl.log');
+ $this->logFilePointer = fopen(FULL_PATH.DBG_CURL_LOGFILE, 'a');
+
+ curl_setopt($this->connectionID, CURLOPT_FILE, $this->logFilePointer);
+ curl_setopt($this->connectionID, CURLOPT_VERBOSE, true);
+ curl_setopt($this->connectionID, CURLOPT_STDERR, $this->logFilePointer);
+ //curl_setopt($this->connectionID, CURLOPT_WRITEHEADER, $this->logFilePointer);
+ }
+
+ $this->responceHeaders = Array ();
+
+ $this->prepareOptions();
+ $this->lastRespoce = curl_exec($this->connectionID);
+
+ $this->Finalize($close_connection);
+
+ return $this->lastRespoce;
+ }
+
+ /**
+ * Returns various info about request made
+ *
+ * @param int $info_type
+ * @return mixed
+ *
+ * @see http://www.php.net/manual/ru/function.curl-getinfo.php
+ */
+ function getInfo($info_type)
+ {
+ return curl_getinfo($this->connectionID, $info_type);
+ }
+
+ function Finalize($close_connection = true)
+ {
+ $this->lastErrorCode = curl_errno($this->connectionID);
+ $this->lastErrorMsg = curl_error($this->connectionID);
+ $this->lastHTTPCode = curl_getinfo($this->connectionID, CURLINFO_HTTP_CODE);
+
+ if ($this->debugMode) {
+ fwrite($this->logFilePointer, "\n".$this->lastRespoce);
+ fclose($this->logFilePointer);
+ }
+
+ $this->_resetSettings();
+
+ if ($close_connection) {
+ $this->CloseConnection();
+ }
+ }
+
+ function CloseConnection()
+ {
+ curl_close($this->connectionID);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/curl_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.4.4
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/geocode_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/geocode_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/geocode_helper.php (revision 12306)
@@ -0,0 +1,186 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class GeoCodeHelper extends kHelper {
+
+ /**
+ * Returns Longitude & Latitude by US address provided
+ *
+ * @param Array $data
+ * @return Array
+ */
+ function QueryCoordinates($address, $city, $state, $zip)
+ {
+ $user = $this->Application->ConfigValue('GeoCodeUser');
+ $pass = $this->Application->ConfigValue('GeoCodePass');
+
+ $rie_path = sprintf(FULL_PATH.'/tools/rie/rie -u %s -p %s -g "%s" -l',
+ $user,
+ $pass,
+ $address.'|'.$city.'|'.$state.'|'.$zip
+ );
+
+ exec($rie_path, $geo_array, $code);
+
+ if ($code == 0) {
+ $out_data = explode('|', $geo_array[2]);
+
+// include_once(FULL_PATH.'/compat/array_combine.php');
+ $assoc_data = array_combine(explode('|', $geo_array[1]), $out_data);
+
+ $lon = abs($out_data[8]); // set to positive, because required by SQL formula
+ $lat = $out_data[7];
+
+ $zip4 = $out_data[9];
+ $dpbc = $out_data[10];
+ $carrier = $out_data[11];
+ }
+ else {
+ $lon = '';
+ $lat = '';
+ $zip4 = '';
+ $dpbc = '';
+ $carrier = '';
+ $assoc_data = Array();
+ }
+
+ return Array($lon, $lat, $zip4, $dpbc, $carrier, serialize($assoc_data));
+ }
+
+ function getTag($tag, $xml)
+ {
+ $open_tag_pos = strpos($xml, '<'.$tag.'>');
+ $close_tag_pos = strpos($xml, '</'.$tag.'>');
+ if (!$open_tag_pos || !$close_tag_pos)
+ {
+ return '';
+ }
+ $tag_length = strlen($tag) + 2;
+ return substr($xml, $open_tag_pos + $tag_length, $close_tag_pos - $open_tag_pos - $tag_length);
+ }
+
+ function QueryCoordinatesFromGoogle($address, $city, $state, $zip)
+ {
+ // 1908 Pike pl, Seattle, WA
+ // http://maps.google.com/maps/geo?
+ // ABQIAAAAzNbTbxHki-PAnXzsrA7z2hR0fs2_a3JecCfKmMFhGT8VtEjV7xRV8rMK1czaEH2ZG3eiYJMuej_vnQ
+
+ $qaddress = $address.', '.$city.', '.$state;
+ $request_url = $this->Application->ConfigValue('GoogleMapsURL').'output=xml&key='.
+ $this->Application->ConfigValue('GoogleMapsKey').'&q='.urlencode($qaddress);
+
+ $curl_helper =& $this->Application->recallObject('CurlHelper');
+ /* @var $curl_helper kCurlHelper */
+
+ $delay = 0;
+ while (true)
+ {
+ $xml = $curl_helper->Send($request_url);
+
+ if (strpos($xml, '<code>620</code>')) {
+ $delay += 100000;
+ } elseif (strpos($xml, '<code>200</code>')) {
+ // get latitude, longitude and zip from xml-answer
+ $a_coords = explode(',', $this->getTag('coordinates', $xml));
+ $lat = $a_coords[1];
+ $lon = abs($a_coords[0]); // set to positive, because required by SQL formula
+ $zip4 = $this->getTag('PostalCodeNumber', $xml);
+ $dpbc = '';
+ $carrier = '';
+ $assoc_data = Array();
+ break;
+ } else {
+ $lon = '';
+ $lat = '';
+ $zip4 = '';
+ $dpbc = '';
+ $carrier = '';
+ $assoc_data = Array();
+ break;
+ }
+ usleep($delay);
+ }
+
+ return Array($lon, $lat, $zip4, $dpbc, $carrier, serialize($assoc_data));
+
+ }
+
+ /**
+ * Try to find lon, lat by address return false if failed
+ *
+ * @param string $address
+ * @param string $city
+ * @param string $state
+ * @param int $zip
+ * @return Array (lon, lat)
+ */
+ function GetCoordinates($address, $city, $state, $zip, $no_cache = false, $force_cache = false)
+ {
+ if (!$zip && !$state) {
+ // if state or zip missing then do nothing
+ return false;
+ }
+
+ $zip_info = $no_cache ? false : $this->GetFromCache($address, $city, $state, $zip);
+// $zip_info = $this->GetFromCache($address, $city, $state, $zip);
+
+ if (!$zip_info && !$force_cache) {
+ list($lon, $lat, $zip4, $dpbc, $carrier, $geocode_answer) = $this->QueryCoordinatesFromGoogle($address, $city, $state, $zip);
+
+ if ($lon != '' && $lat != '') {
+ // valid position returned by geocode => add to cache
+ $fields_hash = Array(
+ 'zipcode' => $zip4,
+ 'address' => $address,
+ 'city' => $city,
+ 'state' => $state,
+ 'lat' => $lat,
+ 'lon' => $lon,
+ 'zip4' => $zip4,
+ 'dpbc' => $dpbc,
+ 'carrier' => $carrier,
+ 'geocode_answer' => $geocode_answer,
+ );
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'ZipCodes');
+ return Array($lon, $lat, $zip4, $dpbc, $carrier);
+ }
+ else {
+ // bad case, rie call failed => no data retrieved
+ return false;
+ }
+ }
+
+ return Array($zip_info['lon'], $zip_info['lat'], getArrayValue($zip_info, 'zip4'), getArrayValue($zip_info, 'dpbc'), getArrayValue($zip_info, 'carrier'));
+ }
+
+ /**
+ * Try to find cached lon, lat by address
+ *
+ * @param string $address
+ * @param string $city
+ * @param string $state
+ * @param int $zip
+ * @return Array (lon, lat)
+ */
+ function GetFromCache($address, $city, $state, $zip)
+ {
+ $zip = substr($zip, 0, 5); // use only first 5 digits
+ $sql = 'SELECT lon, lat
+ FROM '.TABLE_PREFIX.'ZipCodes
+ WHERE zipcode = '.$this->Conn->qstr($zip);
+ return $this->Conn->GetRow($sql);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/geocode_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.72.2
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/modules.php
===================================================================
--- branches/5.0.x/core/units/helpers/modules.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/modules.php (revision 12306)
@@ -0,0 +1,435 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kModulesHelper extends kHelper {
+
+ function getWhereClause()
+ {
+ $where_clause = Array('Loaded = 1');
+
+ if (!$this->Application->IsAdmin()) return implode(' AND ', $where_clause);
+
+ $modules = $this->_GetModules();
+ if ($modules) {
+ foreach ($modules as $module_index => $module) {
+ $modules[$module_index] = $this->Conn->qstr($module);
+ }
+ $where_clause[] = 'Name IN ('.implode(',', $modules).')';
+ }
+
+ return implode(' AND ', $where_clause);
+ }
+
+ function _EnableCookieSID()
+ {
+ $session =& $this->Application->recallObject('Session');
+ return $session->CookiesEnabled;
+ }
+
+ function _IsSpider($UserAgent)
+ {
+ global $robots;
+ $lines = file(FULL_PATH.'/robots_list.txt');
+
+ if (!is_array($robots)) {
+ $robots = Array();
+ for($i = 0; $i < count($lines); $i++) {
+ $l = $lines[$i];
+ $p = explode("\t", $l, 3);
+ $robots[] = $p[2];
+ }
+ }
+ return in_array($UserAgent, $robots);
+ }
+
+ function _MatchIp($ip1, $ip2)
+ {
+ $matched = TRUE;
+
+ $ip = explode('.', $ip1);
+ $MatchIp = explode('.', $ip2);
+ for ($i = 0; $i < count($ip); $i++) {
+ if($i == count($MatchIp)) break;
+ if (trim($ip[$i]) != trim($MatchIp[$i]) || trim($ip[$i]) == '*') {
+ $matched = FALSE;
+ break;
+ }
+ }
+ return $matched;
+ }
+
+ function _IpAccess($IpAddress, $AllowList, $DenyList)
+ {
+ $allowed = explode(',', $AllowList);
+ $denied = explode(',', $DenyList);
+
+ $MatchAllowed = FALSE;
+ for ($x = 0; $x < count($allowed); $x++) {
+ $ip = explode('.', $allowed[$x]);
+
+ $MatchAllowed = $this->_MatchIp($IpAddress, $allowed[$x]);
+ if ($MatchAllowed)
+ break;
+ }
+ $MatchDenied = FALSE;
+ for ($x = 0; $x < count($denied); $x++) {
+ $ip = explode('.', $denied[$x]);
+
+ $MatchDenied = $this->_MatchIp($IpAddress, $denied[$x]);
+ if ($MatchDenied)
+ break;
+ }
+
+ $Result = (($MatchAllowed && !$MatchDenied) || (!$MatchAllowed && !$MatchDenied) ||
+ ($MatchAllowed && $MatchDenied));
+ return $Result;
+ }
+
+ /**
+ * Leaves only domain part from hostname (e.g. extract "intechnic.lv" from "test.intechnic.lv")
+ * Used for admin login license check
+ *
+ * @param string $d
+ * @return string
+ */
+ function _StripDomainHost($d)
+ {
+ $IsIp = false;
+ $dotcount = substr_count($d, '.');
+ if ($dotcount == 3) {
+ $IsIp = true;
+ for ($x = 0; $x < strlen($d); $x++) {
+ if (!is_numeric(substr($d, $x, 1)) && substr($d, $x, 1) != '.')
+ {
+ $IsIp = false;
+ break;
+ }
+ }
+ }
+
+ if ($dotcount > 1 && !$IsIp) {
+ $p = explode('.', $d);
+ $ret = $p[count($p) - 2].'.'.$p[count($p) - 1];
+ }
+ else {
+ $ret = $d;
+ }
+ return $ret;
+ }
+
+ /**
+ * When logging into admin then check only last 2 parts of host name VS domain in license
+ *
+ * @param string $user_domain
+ * @param string $license_domain
+ * @return int
+ */
+ function _CheckDomain($user_domain, $license_domain)
+ {
+ if ($this->Application->IsAdmin()) {
+ $user_domain = $this->_StripDomainHost($user_domain);
+ return preg_match('/(.*)'.preg_quote($user_domain, '/').'$/', $license_domain);
+ }
+ else {
+ return preg_match('/(.*)'.preg_quote($license_domain, '/').'$/', $user_domain);
+ }
+ }
+
+ /**
+ * Returns modules list, that are in license
+ *
+ * @return Array
+ */
+ function _GetModules()
+ {
+ static $modules = null;
+
+ if (isset($modules)) {
+ return $modules;
+ }
+
+ $modules = Array();
+ $vars = parse_portal_ini(FULL_PATH . DIRECTORY_SEPARATOR . 'config.php');
+ $license = array_key_exists('License', $vars) ? base64_decode($vars['License']) : false;
+ if ($license) {
+ list ( , , $i_Keys) = $this->_ParseLicense($license);
+ $domain = $this->_GetDomain($vars);
+ if (!$this->_IsLocalSite($domain)) {
+ for ($x = 0; $x < count($i_Keys); $x++) {
+ $key = $i_Keys[$x];
+ if ($this->_CheckDomain($domain, $key['domain'])) {
+ // used hostname is subdomain or matches domain from license
+ $modules = explode(',', $key['mod']);
+ }
+ }
+ }
+ else {
+ // all already installed modules are licensed for localhost
+ $modules = array_keys($this->Application->ModuleInfo);
+ }
+ }
+
+ // all modules starting from "in-" doesn't require license
+ $base_modules = Array ('Core', 'In-Portal', 'Custom');
+ $modules = array_merge($modules, $base_modules, $this->_getFreeModules($vars));
+ $modules = array_unique( array_map('strtolower', $modules) );
+
+ return $modules;
+ }
+
+ /**
+ * Get all modules, that don't require licensing
+ *
+ * @return Array
+ */
+ function _getFreeModules($vars)
+ {
+ $skip_modules = Array ('.', '..');
+ $domain = $this->_GetDomain($vars);
+
+ if (!$this->_IsLocalSite($domain)) {
+ array_push($skip_modules, 'in-commerce', 'in-auction');
+ }
+
+ $folder = dir(MODULES_PATH);
+
+ $ret = Array ();
+ while (($entry = $folder->read()) !== false) {
+ $entry_lowercased = strtolower($entry);
+ if (!is_dir($folder->path . '/' . $entry) || in_array($entry_lowercased, $skip_modules) || (substr($entry_lowercased, 0, 3) != 'in-')) {
+ continue;
+ }
+
+ $ret[] = $entry_lowercased;
+ }
+
+ $folder->close();
+
+ return $ret;
+ }
+
+ /**
+ * Allows to determine if module is licensed
+ *
+ * @param string $name
+ * @return bool
+ */
+ function _ModuleLicensed($name)
+ {
+ $modules = $this->_GetModules();
+ return in_array($name, $modules);
+ }
+
+ /**
+ * Returns domain from licences (and direct in case of install script)
+ *
+ * @return string
+ */
+ function _GetDomain($vars)
+ {
+ $config_domain = array_key_exists('Domain', $vars) ? $vars['Domain'] : false;
+ return $this->Application->ConfigValue('DomainDetect') ? $_SERVER['HTTP_HOST'] : $config_domain;
+ }
+
+ function _keyED($txt, $encrypt_key)
+ {
+ $encrypt_key = md5($encrypt_key);
+ $ctr = 0;
+ $tmp = '';
+ for ($i = 0; $i < strlen($txt); $i++) {
+ if ($ctr == strlen($encrypt_key)) $ctr = 0;
+ $tmp .= substr($txt, $i, 1) ^ substr($encrypt_key, $ctr, 1);
+ $ctr++;
+ }
+ return $tmp;
+ }
+
+
+ function _decrypt($txt, $key)
+ {
+ $txt = $this->_keyED($txt,$key);
+ $tmp = '';
+ for ($i = 0; $i < strlen($txt); $i++) {
+ $md5 = substr($txt, $i, 1);
+ $i++;
+ $tmp .= (substr($txt, $i, 1) ^ $md5);
+ }
+ return $tmp;
+ }
+
+ function LoadFromRemote()
+ {
+ return '';
+ }
+
+ function DLid()
+ {
+ die($GLOBALS['lid']."\n");
+ }
+
+ function _LoadLicense($LoadRemote = false)
+ {
+ $f = FULL_PATH.'/intechnic.php';
+ if ($this->_falseIsLocalSite($f)) $ret = true;
+ if (file_exists($f)) {
+ $contents = file($f);
+ $data = base64_decode($contents[1]);
+ }
+ else {
+ if ($LoadRemote) return $LoadFromRemote;
+ }
+ return $data;
+ }
+
+ function _VerifyKey($domain, $k)
+ {
+ $key = md5($domain);
+ $lkey = substr($key, 0, strlen($key) / 2);
+ $rkey = substr($key, strlen($key) / 2);
+ $r = $rkey.$lkey;
+ if ($k == $r) return true;
+ return false;
+ }
+
+ function _ParseLicense($txt)
+ {
+// global $i_User, $i_Pswd, $i_Keys;
+
+ if (!$this->_falseIsLocalSite($txt)) {
+ $nah = false;
+ }
+
+ $data = $this->_decrypt($txt, 'beagle');
+ $i_User = $i_Pswd = '';
+ $i_Keys = Array();
+ $lines = explode("\n", $data);
+ for ($x = 0; $x < count($lines); $x++) {
+ $l = $lines[$x];
+ $p = explode('=', $l, 2);
+ switch($p[0]) {
+ case 'Username':
+ $i_User = $p[1];
+ break;
+
+ case 'UserPass':
+ $i_Pswd = $p[1];
+ break;
+
+ default:
+ if (substr($p[0], 0, 3) == 'key') {
+ $parts = explode('|', $p[1]);
+ if ($this->_VerifyKey($parts[0], $parts[1])) {
+ unset($K);
+ $k['domain'] = $parts[0];
+ $k['key'] = $parts[1];
+ $k['desc'] = $parts[2];
+ $k['mod'] = $parts[3];
+ $i_Keys[] = $k;
+ }
+ }
+ break;
+ }
+ }
+
+ return Array ($i_User, $i_Pswd, $i_Keys);
+ }
+
+ function _GetObscureValue($i)
+ {
+ if ($i == 'x') return 0254; $z = '';
+ if ($i == 'z') return 0x7F.'.';
+ if ($i == 'c') return '--code--';
+ if ($i >= 5 && $i < 7) return $this->_GetObscureValue($z)*$this->_GetObscureValue('e');
+ if ($i > 30) return Array(0x6c,0x6f,0x63,0x61,0x6c,0x68,0x6f,0x73,0x74);
+ if ($i > 20) return 99;
+ if ($i > 10) return '.'.($this->_GetObscureValue(6.5)+1);
+ if ($i == 'a') return 0xa;
+ }
+
+ function _Chr($val)
+ {
+ $x = $this->_GetObscureValue(25);
+ $f = chr($x).chr($x+5).chr($x+15);
+ return $f($val);
+ }
+
+ function _IsLocalSite($domain)
+ {
+ $ee = $this->_GetObscureValue(35); $yy = '';
+ foreach ($ee as $e) $yy .= $this->_Chr($e);
+ $localb = FALSE;
+ if(substr($domain,0,3)==$this->_GetObscureValue('x'))
+ {
+ $b = substr($domain,0,6);
+ $p = explode(".",$domain);
+ $subnet = $p[1];
+ if($p[1]>15 && $p[1]<32)
+ $localb=TRUE;
+ }
+ $zz = $this->_GetObscureValue('z').$this->_GetObscureValue(5).'.'.(int)$this->_GetObscureValue(7).$this->_GetObscureValue(12);
+ $ff = $this->_GetObscureValue('z')+65;
+ $hh = $ff-0x18;
+ if($domain==$yy || $domain==$zz || substr($domain,0,7)==$ff.$this->_Chr(46).$hh ||
+ substr($domain,0,3)==$this->_GetObscureValue('a').$this->_Chr(46) || $localb || strpos($domain,".")==0)
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ function _falseIsLocalSite($domain)
+ {
+ $localb = FALSE;
+ if(substr($domain,0,3)=="172")
+ {
+ $b = substr($domain,0,6);
+ $p = explode(".",$domain);
+ $subnet = $p[1];
+ if($p[1]>15 && $p[1]<32)
+ $localb=TRUE;
+ }
+ if($domain=="localhost" || $domain=="127.0.0.1" || substr($domain,0,7)=="192.168" ||
+ substr($domain,0,3)=="10." || $localb || strpos($domain,".")==0)
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ function verifyLicense($license_hash)
+ {
+ $license_hash = base64_decode($license_hash);
+ list ($license_user, $license_password, ) = $this->_ParseLicense($license_hash);
+ return strlen($license_user) && strlen($license_password);
+ }
+
+ function moduleInstalled($module_name)
+ {
+ static $modules = null;
+
+ if (is_null($modules)) {
+ $sql = 'SELECT LOWER(Name)
+ FROM ' . $this->Application->getUnitOption('mod', 'TableName');
+ $modules = $this->Conn->GetCol($sql);
+ }
+
+ if ($module_name == 'kernel') {
+ $module_name = 'in-portal';
+ }
+
+ return in_array(strtolower($module_name), $modules);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/modules.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.10.2.5
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/json_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/json_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/json_helper.php (revision 12306)
@@ -0,0 +1,167 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class JSONHelper extends kHelper {
+
+// var $match = Array ('\\', "\n", "\t", "\r", "\b", "\f", '"');
+// var $replace = Array ('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
+
+// \x{2028} is some strange char found in GTA responses... it breaks javascript
+ var $match = Array ('/\\\\/u', '/\\"/u', '/\\t/u', '/\\n/u', '/\\r/u', '/\\x{2028}/u');
+ var $replace = Array ('\\\\\\\\', '\\"', '\\t', '\\n', '\\r', '');
+
+ /**
+ * Object constructor
+ *
+ * @return JSONHelper
+ */
+ function JSONHelper() {
+
+ }
+
+ /**
+ * Parse structure to JSON
+ *
+ * @param mixed $data
+ * @return string
+ */
+ function parse($data)
+ {
+ return '('.$this->encode($data).')';
+ }
+
+ /**
+ * Converts PHP variable to JSON string
+ * Can convert any PHP variable with any content to correct JSON structure
+ *
+ * @param mixed $data Data to convert
+ * @return string
+ */
+ function encode($data)
+ {
+ $type = $this->getType($data);
+
+ switch ($type) {
+ case 'object':
+ $data = '{'.$this->processData($data, $type).'}';
+ break;
+ case 'array':
+ $data = '['.$this->processData($data, $type).']';
+ break;
+ default:
+ if (is_int($data) || is_float($data)) {
+ $data = (string)$data;
+ } elseif (is_string($data)) {
+ $data = '"'.$this->escape($data).'"';
+ } elseif (is_bool($data)) {
+ $data = $data ? 'true' : 'false';
+ } else {
+ $data = 'null';
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param unknown_type $input
+ * @param unknown_type $type
+ * @return unknown
+ */
+ function processData($data, $type)
+ {
+ $output = Array();
+ // If data is an object - it should be converted as a key => value pair
+
+ if ($type == 'object'){
+ foreach($data as $key => $value) {
+ $output[] = '"'.$key.'": '.$this->encode($value);
+ }
+ } else {
+ foreach($data as $key => $value) {
+ $output[] = $this->encode($value);
+ }
+ }
+ return implode(',', $output);;
+ }
+
+ /**
+ * Function determines type of variable
+ *
+ * @param unknown_type $data
+ * @return unknown
+ */
+ function getType(&$data)
+ {
+ if (is_object($data)) {
+ $type = 'object';
+ } elseif (is_array($data)) {
+ // If array is assoc it should be processed as an object
+ if($this->is_assoc($data)) {
+ $type = 'object';
+ } else {
+ $type = 'array';
+ }
+ } elseif (is_numeric($data)) {
+ $type = 'number';
+ } elseif(is_string($data)) {
+ $type = 'string';
+ } elseif(is_bool($data)) {
+ $type = 'boolean';
+ } elseif(is_null($data)) {
+ $type = 'null';
+ } else {
+ $type = 'string';
+ }
+ return $type;
+ }
+
+ /**
+ * Function determines if array is associative
+ *
+ * @param array $array
+ * @return bool
+ */
+ function is_assoc($array)
+ {
+// Arrays are defined as integer-indexed arrays starting at index 0, where
+// the last index is (count($array) -1); any deviation from that is
+// considered an associative array, and will be encoded as such (from Zend Framework).
+
+ return !empty($array) && (array_keys($array) !== range(0, count($array) - 1));
+ }
+
+ /**
+ * Escapes special characters
+ * Function escapes ", \, /, \n and \r symbols so that not to cause JavaScript error or
+ * data loss
+ *
+ * @param string $string
+ * @return string
+ */
+ function escape($string)
+ {
+ $string = preg_replace($this->match, $this->replace, $string);
+
+ return $string;
+
+ // Escape certain ASCII characters:
+ // 0x08 => \b
+ // 0x0c => \f
+// return str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/json_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.2.2
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/col_picker_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/col_picker_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/col_picker_helper.php (revision 12306)
@@ -0,0 +1,204 @@
+<?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.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+class kColumnPickerHelper extends kHelper {
+
+ var $PickerData;
+ var $GridName;
+ var $UseFreezer;
+
+ function Init($prefix,$special,$event_params=null)
+ {
+ parent::Init($prefix, $special, $event_params);
+ $this->UseFreezer = $this->Application->ConfigValue('UseColumnFreezer');
+ }
+
+ function LoadColumns($prefix)
+ {
+ $view_name = $this->Application->RecallVar($prefix.'_current_view');
+ $val = $this->Application->RecallPersistentVar($prefix.'_columns_.'.$view_name, ALLOW_DEFAULT_SETTINGS);
+
+ if (!$val) {
+ $cols = $this->RebuildColumns($prefix);
+ }
+ else {
+ $cols = unserialize($val);
+ $current_cols = $this->GetColumns($prefix);
+
+ if ($cols === false || $cols['crc'] != $current_cols['crc'])
+ {
+ $cols = $this->RebuildColumns($prefix, $cols);
+ }
+ }
+ return $cols;
+ }
+
+ function PreparePicker($prefix, $grid_name)
+ {
+ $this->SetGridName($grid_name);
+ $this->PickerData = $this->LoadColumns($prefix);
+ }
+
+ function ApplyPicker($prefix, &$fields, $grid_name)
+ {
+ $this->PreparePicker($prefix, $grid_name);
+ uksort($fields, array($this, 'CmpElems'));
+ $this->RemoveHiddenColumns($fields);
+ }
+
+ function SetGridName($grid_name)
+ {
+ $this->GridName = $grid_name;
+ }
+
+ function CmpElems($a, $b)
+ {
+ $a_index = array_search($a, $this->PickerData['order']);
+ $b_index = array_search($b, $this->PickerData['order']);
+
+ if ($a_index == $b_index) {
+ return 0;
+ }
+ return ($a_index < $b_index) ? -1 : 1;
+ }
+
+ function RebuildColumns($prefix, $current=null)
+ {
+ $cols = $this->GetColumns($prefix);
+
+ if (is_array($current)) {
+ //get common fields both in db and xml
+ $common = array_intersect($current['order'], $cols['order']);
+
+ //get added columns - present in xml, but not in db
+ $added = array_diff($cols['order'], $current['order']);
+ if (in_array('__FREEZER__', $added)) {
+ array_unshift($common, '__FREEZER__');
+ unset($added[array_search('__FREEZER__', $added)]);
+ }
+
+ $cols['order'] = array_merge($common, $added);
+ $cols['hidden_fields'] = array_intersect($current['order'], $current['hidden_fields']);
+ foreach($common as $col) {
+ $cols['widths'][$col] = isset($current['widths'][$col]) ? $current['widths'][$col] : 100;
+ }
+ $this->SetCRC($cols);
+ }
+ $this->StoreCols($prefix, $cols);
+
+ return $cols;
+ }
+
+ function StoreCols($prefix, $cols)
+ {
+ $view_name = $this->Application->RecallVar($prefix.'_current_view');
+ $this->Application->StorePersistentVar($prefix.'_columns_.'.$view_name, serialize($cols));
+ }
+
+ function GetColumns($prefix)
+ {
+ $splited = $this->Application->processPrefix($prefix);
+ $grids = $this->Application->getUnitOption($splited['prefix'], 'Grids');
+ $conf_fields = $this->UseFreezer ? array_merge_recursive(
+ array('__FREEZER__' => array('title' => '__FREEZER__')),
+ $grids[$this->GridName]['Fields']
+ ) : $grids[$this->GridName]['Fields'];
+// $conf_fields = $grids[$this->GridName]['Fields'];
+
+ // we NEED to recall dummy here to apply fields changes imposed by formatters,
+ // such as replacing multilingual field titles etc.
+ $dummy =& $this->Application->recallObject($prefix, null, array('skip_autoload'=>1));
+
+ $counter = 0;
+ $hidden = array();
+ $fields = array();
+ $titles = array();
+ $widths = array();
+ foreach ($conf_fields as $name => $options) {
+ $fields[$counter] = $name;
+ $titles[$name] = $options['title'];
+ $widths[$name] = array_key_exists('width', $options) ? $options['width'] : 100; // only once per grid !
+ if (isset($options['hidden']) && $options['hidden'])
+ {
+ $hidden[$counter] = $name;
+ }
+ $counter++;
+ }
+ $sorted_fields = $fields;
+ sort($sorted_fields);
+ $cols = array(
+ 'order' => $fields,
+ 'titles' => $titles,
+ 'hidden_fields' => $hidden,
+ 'widths' => $widths,
+ );
+ $this->SetCRC($cols);
+ return $cols;
+ }
+
+ function SetCRC(&$cols)
+ {
+ $sorted_fields = $cols['order'];
+ $sorted_titles = $cols['titles'];
+ asort($sorted_fields);
+ asort($sorted_titles);
+ $cols['crc'] = crc32(implode(',', $sorted_fields).implode(',', $sorted_titles));
+ }
+
+ function RemoveHiddenColumns(&$fields)
+ {
+ $to_remove = array();
+ foreach ($fields as $name => $options) {
+ if (array_search($name, $this->PickerData['hidden_fields']) !== false) {
+ $to_remove[] = $name;
+ }
+ }
+ foreach ($to_remove as $name) {
+ unset($fields[$name]);
+ }
+ }
+
+ function SaveColumns($prefix, $picked, $hidden)
+ {
+ $order = $picked ? explode('|', $picked) : array();
+ $hidden = $hidden ? explode('|', $hidden) : array();
+ $order = array_merge($order, $hidden);
+
+ $cols = $this->LoadColumns($prefix);
+ $cols['order'] = $order;
+ $cols['hidden_fields'] = $hidden;
+
+ $this->SetCRC($cols);
+ $this->StoreCols($prefix, $cols);
+ }
+
+ function SaveWidths($prefix, $widths)
+ {
+ if (!is_array($widths)) $widths = explode(':', $widths);
+ array_shift($widths); // removing first col (checkbox col) width
+ $i = 0;
+ foreach ($this->PickerData['order'] as $ord => $field) {
+ if ($field == '__FREEZER__') continue;
+ $this->PickerData['widths'][$field] = $widths[$i++];
+ }
+ $this->StoreCols($prefix, $this->PickerData);
+ }
+
+ function GetWidth($field)
+ {
+ return isset($this->PickerData['widths'][$field]) ? $this->PickerData['widths'][$field] : false;
+ }
+}
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/col_picker_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.2.2.4
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/mailing_list_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/mailing_list_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/mailing_list_helper.php (revision 12306)
@@ -0,0 +1,284 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class MailingListHelper extends kHelper {
+
+ var $_mailingId = false;
+
+ /**
+ * Adds new email from given mailing to emails queue
+ *
+ * @param string $email
+ * @param int $mailing_id
+ * @param Array $mailing_data
+ */
+ function queueEmail($email, $mailing_id, &$mailing_data)
+ {
+ $esender =& $this->Application->recallObject('EmailSender');
+ /* @var $esender kEmailSendingHelper */
+
+ if ($this->_mailingId != $mailing_id) {
+ if (is_numeric($this->_mailingId)) {
+ // clear fields after previous mailing processing
+ $esender->Clear();
+ }
+
+ // 1. set headers same for all emails
+ list ($mailing_data['FromName'], $mailing_data['FromEmail']) = $this->_getSenderData($mailing_data);
+ $esender->SetFrom($mailing_data['FromEmail'], $mailing_data['FromName']);
+
+ $esender->SetSubject($mailing_data['Subject']);
+ $esender->SetBody($mailing_data['MessageHtml'], $mailing_data['MessageText']);
+
+ // 2. add attachment if any
+ $attachments = $mailing_data['Attachments'] ? explode('|', $mailing_data['Attachments']) : Array ();
+
+ foreach ($attachments as $attachment) {
+ $esender->AddAttachment(FULL_PATH . ITEM_FILES_PATH . $attachment);
+ }
+
+ $this->_mailingId = $mailing_id;
+ }
+
+ // 3. set recipient specific fields
+ $esender->SetTo($email, $email);
+ $esender->Deliver(null, $mailing_id, false);
+
+ // 4. write to log
+ $log_fields_hash = Array (
+ 'fromuser' => $mailing_data['FromName'] . '<' . $mailing_data['FromEmail'] . '>',
+ 'addressto' => $email,
+ 'subject' => $mailing_data['Subject'],
+ 'timestamp' => adodb_mktime(),
+ 'EventParams' => serialize( Array ('MailingId' => $mailing_id) ),
+ );
+
+ $this->Conn->doInsert($log_fields_hash, TABLE_PREFIX . 'EmailLog');
+ }
+
+ /**
+ * Returns mass mail sender name & email
+ *
+ * @return Array
+ */
+ function _getSenderData(&$mailing_data)
+ {
+ $is_root = true;
+ if ($mailing_data['PortalUserId'] > 0) {
+ $sender =& $this->Application->recallObject('u.-item', null, Array ('skip_autoload' => true));
+ /* @var $sender UsersItem */
+
+ $sender->Load($mailing_data['PortalUserId']);
+
+ $email_address = $sender->GetDBField('Email');
+ $name = trim( $sender->GetDBField('FirstName') . ' ' . $sender->GetDBField('LastName') );
+ $is_root = false;
+ }
+
+ if ($is_root || !$email_address) {
+ $email_address = $this->Application->ConfigValue('Smtp_AdminMailFrom');
+ }
+
+ if ($is_root || !$name) {
+ $name = strip_tags( $this->Application->ConfigValue('Site_Name') );
+ }
+
+ return Array ($name, $email_address);
+ }
+
+ /**
+ * Generates recipients emails based on "To" field value
+ *
+ * @param int $id
+ * @param Array $fields_hash
+ */
+ function generateRecipients($id, $fields_hash)
+ {
+ $recipients = explode(';', $fields_hash['To']);
+
+ // 1. group recipients by types
+ $recipients_grouped = Array ();
+ foreach ($recipients as $recipient) {
+ if (strpos($recipient, '_') !== false) {
+ list ($recipient_type, $recipient_id) = explode('_', $recipient);
+ }
+ else {
+ $recipient_type = 'direct';
+ $recipient_id = $recipient;
+ }
+
+ if (!array_key_exists($recipient_type, $recipients_grouped)) {
+ $recipients_grouped[$recipient_type] = Array ();
+ }
+
+ $recipients_grouped[$recipient_type][] = $recipient_id;
+ }
+
+ // for each group convert ids to names
+ $recpient_emails = Array ();
+ foreach ($recipients_grouped as $recipient_type => $group_recipients) {
+ $recpient_emails = array_merge($recpient_emails, $this->_getRecipientEmails($recipient_type, $group_recipients));
+ }
+
+ $recpient_emails = array_unique($recpient_emails);
+
+ return Array (
+ 'ToParsed' => serialize($recpient_emails),
+ 'EmailsTotal' => count($recpient_emails),
+ );
+ }
+
+ function _getRecipientEmails($recipient_type, $recipient_ids)
+ {
+ if (strpos($recipient_type, '.') !== false) {
+ // remove special
+ list ($recipient_type, ) = explode('.', $recipient_type);
+ }
+
+ if ($recipient_type != 'u' && $recipient_type != 'g') {
+ // theese are already emails
+ return $recipient_ids;
+ }
+
+ switch ($recipient_type) {
+ case 'u':
+ $sql = 'SELECT Email
+ FROM ' . TABLE_PREFIX . 'PortalUser
+ WHERE (PortalUserId IN (' . implode(',', $recipient_ids) . ')) AND (Email <> "")';
+ break;
+
+ case 'g':
+ $sql = 'SELECT u.Email
+ FROM ' . TABLE_PREFIX . 'UserGroup ug
+ LEFT JOIN ' . TABLE_PREFIX . 'PortalUser u ON u.PortalUserId = ug.PortalUserId
+ WHERE (ug.GroupId IN (' . implode(',', $recipient_ids) . ')) AND (u.Email <> "")';
+ break;
+ }
+
+ return $this->Conn->GetCol($sql);
+ }
+
+ function getRecipientNames($recipient_type, $recipient_ids)
+ {
+ if (strpos($recipient_type, '.') !== false) {
+ // remove special
+ list ($recipient_type, ) = explode('.', $recipient_type);
+ }
+
+ switch ($recipient_type) {
+ case 'u':
+ $title_field = 'Email';
+ break;
+
+ case 'g':
+ $title_field = 'Name';
+ break;
+
+ default:
+ $title_field = false;
+ break;
+ }
+
+ if ($title_field === false || !$recipient_ids) {
+ return $recipient_ids;
+ }
+
+ $id_field = $this->Application->getUnitOption($recipient_type, 'IDField');
+ $table_name = $this->Application->getUnitOption($recipient_type, 'TableName');
+
+ $sql = 'SELECT ' . $title_field . '
+ FROM ' . $table_name . '
+ WHERE ' . $id_field . ' IN (' . implode(',', $recipient_ids) . ')';
+ return $this->Conn->GetCol($sql);
+ }
+
+ /**
+ * Updates information about sent email count based on given totals by mailings
+ *
+ * @param Array $mailing_totals
+ */
+ function _updateSentTotals($mailing_totals)
+ {
+ if (array_key_exists(0, $mailing_totals)) {
+ // don't update sent email count for mails queued directly (not via mailing lists)
+ unset($mailing_totals[0]);
+ }
+
+ $id_field = $this->Application->getUnitOption('mailing-list', 'IDField');
+ $table_name = $this->Application->getUnitOption('mailing-list', 'TableName');
+
+ // update sent email count for each processed mailing
+ foreach ($mailing_totals as $mailing_id => $mailing_total) {
+ $sql = 'UPDATE ' . $table_name . '
+ SET EmailsSent = EmailsSent + ' . $mailing_total . '
+ WHERE ' . $id_field . ' = ' . $mailing_id;
+ $this->Conn->Query($sql);
+ }
+
+ // mark mailings, that were processed completely
+ $sql = 'UPDATE ' . $table_name . '
+ SET Status = ' . MAILING_LIST_PROCESSED . '
+ WHERE (Status = ' . MAILING_LIST_PARTIALLY_PROCESSED . ') AND (EmailsSent = EmailsTotal)';
+ $this->Conn->Query($sql);
+ }
+
+ /**
+ * Sent given messages from email queue
+ *
+ * @param Array $messages
+ */
+ function processQueue(&$messages)
+ {
+ $esender =& $this->Application->recallObject('EmailSender');
+ /* @var $esender kEmailSendingHelper */
+
+ $queue_table = $this->Application->getUnitOption('email-queue', 'TableName');
+
+ $i = 0;
+ $message = Array ();
+ $mailing_totals = Array ();
+ $message_count = count($messages);
+
+ while ($i < $message_count) {
+ $message[0] = unserialize($messages[$i]['MessageHeaders']);
+ $message[1] =& $messages[$i]['MessageBody'];
+ $delivered = $esender->Deliver($message, true); // immediate send!
+
+ if ($delivered) {
+ // send succseeded, delete from queue
+ $sql = 'DELETE FROM ' . $queue_table . '
+ WHERE EmailQueueId = ' . $messages[$i]['EmailQueueId'];
+ $this->Conn->Query($sql);
+
+ $mailing_id = $messages[$i]['MailingId'];
+ if (!array_key_exists($mailing_id, $mailing_totals)) {
+ $mailing_totals[$mailing_id] = 0;
+ }
+ $mailing_totals[$mailing_id]++;
+ }
+ else {
+ // send failed, increment retries counter
+ $sql = 'UPDATE ' . $queue_table . '
+ SET SendRetries = SendRetries + 1, LastSendRetry = ' . adodb_mktime() . '
+ WHERE EmailQueueId = ' . $messages[$i]['EmailQueueId'];
+ $this->Conn->Query($sql);
+ }
+ $i++;
+ }
+
+ $this->_updateSentTotals($mailing_totals);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/mailing_list_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.2.2
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/language_import_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/language_import_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/language_import_helper.php (revision 12306)
@@ -0,0 +1,599 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ define('LANG_OVERWRITE_EXISTING', 1);
+ define('LANG_SKIP_EXISTING', 2);
+
+ class LanguageImportHelper extends kHelper {
+
+ /**
+ * Current Language in import
+ *
+ * @var LanguagesItem
+ */
+ var $lang_object = null;
+
+ /**
+ * Current user's IP address
+ *
+ * @var string
+ */
+ var $ip_address = '';
+
+ /**
+ * Event type + name mapping to id (from system)
+ *
+ * @var Array
+ */
+ var $events_hash = Array ();
+
+ /**
+ * Language pack import mode
+ *
+ * @var int
+ */
+ var $import_mode = LANG_SKIP_EXISTING;
+
+ /**
+ * Language IDs, that were imported
+ *
+ * @var Array
+ */
+ var $_languages = Array ();
+
+ /**
+ * Temporary table names to perform import on
+ *
+ * @var Array
+ */
+ var $_tables = Array ();
+
+ /**
+ * Phrase types allowed for import/export operations
+ *
+ * @var Array
+ */
+ var $phrase_types_allowed = Array ();
+
+ /**
+ * Encoding, used for language pack exporting
+ *
+ * @var string
+ */
+ var $_exportEncoding = 'base64';
+
+ /**
+ * Debug language pack import process
+ *
+ * @var bool
+ */
+ var $_debugMode = false;
+
+ function LanguageImportHelper()
+ {
+ parent::kHelper();
+
+ // "core/install/english.lang", phrase count: 3318, xml parse time on windows: 10s, insert time: 0.058s
+ set_time_limit(0);
+ ini_set('memory_limit', -1);
+
+ $this->lang_object =& $this->Application->recallObject('lang.import', null, Array ('skip_autoload' => true));
+
+ if (!(defined('IS_INSTALL') && IS_INSTALL)) {
+ // perform only, when not in installation mode
+ $this->_updateEventsCache();
+ }
+
+ $this->ip_address = getenv('HTTP_X_FORWARDED_FOR') ? getenv('HTTP_X_FORWARDED_FOR') : getenv('REMOTE_ADDR');
+
+// $this->_debugMode = $this->Application->isDebugMode();
+ }
+
+ /**
+ * Performs import of given language pack (former Parse method)
+ *
+ * @param string $filename
+ * @param string $phrase_types
+ * @param Array $module_ids
+ * @param int $import_mode
+ * @return bool
+ */
+ function performImport($filename, $phrase_types, $module_ids, $import_mode = LANG_SKIP_EXISTING)
+ {
+ // define the XML parsing routines/functions to call based on the handler path
+ if (!file_exists($filename) || !$phrase_types /*|| !$module_ids*/) {
+ return false;
+ }
+
+ if ($this->_debugMode) {
+ $start_time = getmicrotime();
+ $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '")');
+ }
+
+ if (defined('IS_INSTALL') && IS_INSTALL) {
+ // new events could be added during module upgrade
+ $this->_updateEventsCache();
+ }
+
+ $this->_initImportTables();
+
+ $phrase_types = explode('|', substr($phrase_types, 1, -1) );
+// $module_ids = explode('|', substr($module_ids, 1, -1) );
+
+ $this->phrase_types_allowed = array_flip($phrase_types);
+ $this->import_mode = $import_mode;
+
+ $this->_parseXML($filename);
+
+ // copy data from temp tables to live
+ foreach ($this->_languages as $language_id) {
+ $this->_performUpgrade($language_id, 'phrases', 'Phrase');
+ $this->_performUpgrade($language_id, 'emailmessages', 'EventId');
+ }
+
+ $this->_initImportTables(true);
+
+ if ($this->_debugMode) {
+ $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '"): ' . (getmicrotime() - $start_time));
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates XML file with exported language data (former Create method)
+ *
+ * @param string $filename filename to export into
+ * @param Array $phrase_types phrases types to export from modules passed in $module_ids
+ * @param Array $language_ids IDs of languages to export
+ * @param Array $module_ids IDs of modules to export phrases from
+ */
+ function performExport($filename, $phrase_types, $language_ids, $module_ids)
+ {
+ $fp = fopen($filename,'w');
+ if (!$fp || !$phrase_types || !$module_ids || !$language_ids) {
+ return false;
+ }
+
+ $phrase_types = explode('|', substr($phrase_types, 1, -1) );
+ $module_ids = explode('|', substr($module_ids, 1, -1) );
+
+ $this->events_hash = array_flip($this->events_hash);
+
+ $lang_table = $this->Application->getUnitOption('lang','TableName');
+ $phrases_table = $this->Application->getUnitOption('phrases','TableName');
+ $emailevents_table = $this->Application->getUnitOption('emailmessages','TableName');
+ $mainevents_table = $this->Application->getUnitOption('emailevents','TableName');
+
+ $phrase_tpl = "\t\t\t".'<PHRASE Label="%s" Module="%s" Type="%s">%s</PHRASE>'."\n";
+ $event_tpl = "\t\t\t".'<EVENT MessageType="%s" Event="%s" Type="%s">%s</EVENT>'."\n";
+ $sql = 'SELECT * FROM %s WHERE LanguageId = %s';
+ $ret = '<LANGUAGES>'."\n";
+ foreach ($language_ids as $language_id) {
+ // languages
+ $row = $this->Conn->GetRow( sprintf($sql, $lang_table, $language_id) );
+ $ret .= "\t".'<LANGUAGE PackName="'.$row['PackName'].'" Encoding="'.$this->_exportEncoding.'"><DATEFORMAT>'.$row['DateFormat'].'</DATEFORMAT>';
+ $ret .= '<TIMEFORMAT>'.$row['TimeFormat'].'</TIMEFORMAT><INPUTDATEFORMAT>'.$row['InputDateFormat'].'</INPUTDATEFORMAT>';
+ $ret .= '<INPUTTIMEFORMAT>'.$row['InputTimeFormat'].'</INPUTTIMEFORMAT><DECIMAL>'.$row['DecimalPoint'].'</DECIMAL>';
+ $ret .= '<THOUSANDS>'.$row['ThousandSep'].'</THOUSANDS><CHARSET>'.$row['Charset'].'</CHARSET><DOCS_URL>'.$row['UserDocsUrl'].'</DOCS_URL>';
+ $ret .= '<UNITSYSTEM>'.$row['UnitSystem'].'</UNITSYSTEM>'."\n";
+
+ // phrases
+ $phrases_sql = 'SELECT * FROM '.$phrases_table.' WHERE LanguageId = %s AND PhraseType IN (%s) AND Module IN (%s) ORDER BY Phrase';
+ if( in_array('In-Portal',$module_ids) ) array_push($module_ids, ''); // for old language packs
+ $rows = $this->Conn->Query( sprintf($phrases_sql,$language_id, implode(',',$phrase_types), '\''.implode('\',\'',$module_ids).'\'' ) );
+ if($rows)
+ {
+ $ret .= "\t\t".'<PHRASES>'."\n";
+ foreach($rows as $row)
+ {
+ $data = $this->_exportEncoding == 'base64' ? base64_encode($row['Translation']) : '<![CDATA['.$row['Translation'].']]>';
+ $ret .= sprintf($phrase_tpl, $row['Phrase'], $row['Module'], $row['PhraseType'], $data );
+ }
+ $ret .= "\t\t".'</PHRASES>'."\n";
+ }
+
+ // email events
+ if( in_array('In-Portal',$module_ids) ) unset( $module_ids[array_search('',$module_ids)] ); // for old language packs
+ $module_sql = preg_replace('/(.*) OR $/', '\\1', preg_replace('/(.*),/U', 'INSTR(Module,\'\\1\') OR ', implode(',', $module_ids).',' ) );
+
+ $sql = 'SELECT EventId FROM '.$mainevents_table.' WHERE '.$module_sql;
+ $event_ids = $this->Conn->GetCol($sql);
+
+ if($event_ids)
+ {
+ $ret .= "\t\t".'<EVENTS>'."\n";
+ $event_sql = ' SELECT em.*
+ FROM '.$emailevents_table.' em
+ LEFT JOIN '.$mainevents_table.' e ON e.EventId = em.EventId
+ WHERE em.LanguageId = %s AND em.EventId IN (%s)
+ ORDER BY e.Event, e.Type';
+ $rows = $this->Conn->Query( sprintf($event_sql,$language_id, $event_ids ? implode(',',$event_ids) : '' ) );
+ foreach($rows as $row)
+ {
+ if (!array_key_exists($row['EventId'], $this->events_hash)) {
+ // don't export existing translations of missing events
+ continue;
+ }
+
+ list($event_name, $event_type) = explode('_', $this->events_hash[ $row['EventId'] ] );
+ $data = $this->_exportEncoding == 'base64' ? base64_encode($row['Template']) : '<![CDATA['.$row['Template'].']]>';
+ $ret .= sprintf($event_tpl, $row['MessageType'], $event_name, $event_type, $data );
+ }
+ $ret .= "\t\t".'</EVENTS>'."\n";
+ }
+ $ret .= "\t".'</LANGUAGE>'."\n";
+ }
+
+ $ret .= '</LANGUAGES>';
+ fwrite($fp, $ret);
+ fclose($fp);
+
+ return true;
+ }
+
+ /**
+ * Sets language pack encoding (not charset) used during export
+ *
+ * @param string $encoding
+ */
+ function setExportEncoding($encoding)
+ {
+ $this->_exportEncoding = $encoding;
+ }
+
+ /**
+ * Performs upgrade of given language pack part
+ *
+ * @param int $language_id
+ * @param string $prefix
+ * @param string $unique_field
+ */
+ function _performUpgrade($language_id, $prefix, $unique_field)
+ {
+ // TODO: find a way to compare (intersect,diff) phrases in non-case sensitive way, but keeping original case in result
+ $live_records = $this->_getTableData($language_id, $prefix, $unique_field, false);
+ $temp_records = $this->_getTableData($language_id, $prefix, $unique_field, true);
+
+ if ($this->import_mode == LANG_OVERWRITE_EXISTING) {
+ // remove existing records before copy
+ $common_records = array_intersect($temp_records, $live_records);
+ if ($common_records) {
+ $live_records = array_diff($live_records, $common_records); // remove overlaping records
+ $common_records = array_map(Array(&$this->Conn, 'qstr'), $common_records);
+
+ $sql = 'DELETE FROM ' . $this->Application->getUnitOption($prefix, 'TableName') . '
+ WHERE (LanguageId = ' . $language_id . ') AND (' . $unique_field . ' IN (' . implode(',', $common_records) . '))';
+ $this->Conn->Query($sql);
+ }
+ }
+
+ $temp_records = array_diff($temp_records, $live_records);
+
+ if (!$temp_records) {
+ // no new records found in temp table while comparing it to live table
+ return ;
+ }
+
+ $temp_records = array_map(Array(&$this->Conn, 'qstr'), $temp_records);
+
+ $sql = 'INSERT INTO ' . $this->Application->getUnitOption($prefix, 'TableName') . '
+ SELECT *
+ FROM ' . $this->_tables[$prefix] . '
+ WHERE (LanguageId = ' . $language_id . ')';
+
+ if ($live_records) {
+ // subsctract live records from temp table during coping
+ $sql .= ' AND (' . $unique_field . ' IN (' . implode(',', $temp_records) . '))';
+ }
+
+ $this->Conn->Query($sql);
+ }
+
+ /**
+ * Returns data from given table used for language pack upgrade
+ *
+ * @param int $language_id
+ * @param string $prefix
+ * @param string $unique_field
+ * @param bool $temp_mode
+ * @return Array
+ */
+ function _getTableData($language_id, $prefix, $unique_field, $temp_mode = false)
+ {
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+
+ if ($temp_mode) {
+ $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $prefix);
+ }
+
+ $sql = 'SELECT ' . $unique_field . '
+ FROM ' . $table_name . '
+ WHERE LanguageId = ' . $language_id;
+ return $this->Conn->GetCol($sql);
+ }
+
+ function _parseXML($filename)
+ {
+ if ($this->_debugMode) {
+ $start_time = getmicrotime();
+ $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '")');
+ }
+
+ $fdata = file_get_contents($filename);
+
+ $xml_parser =& $this->Application->recallObject('kXMLHelper');
+ /* @var $xml_parser kXMLHelper */
+
+ $root_node =& $xml_parser->Parse($fdata);
+ if (!is_object($root_node) || !is_a($root_node, 'kXMLNode')) {
+ // invalid language pack contents
+ return false;
+ }
+
+ if ($root_node->Children) {
+ $this->_processLanguages($root_node->firstChild);
+ }
+
+ if ($this->_debugMode) {
+ $this->Application->Debugger->appendHTML(__CLASS__ . '::' . __FUNCTION__ . '("' . $filename . '"): ' . (getmicrotime() - $start_time));
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates temporary tables, used during language import
+ *
+ * @param bool $drop_only
+ */
+ function _initImportTables($drop_only = false)
+ {
+ $this->_tables['phrases'] = $this->_prepareTempTable('phrases', $drop_only);
+ $this->_tables['emailmessages'] = $this->_prepareTempTable('emailmessages', $drop_only);
+ }
+
+ /**
+ * Create temp table for prefix, if table already exists, then delete it and create again
+ *
+ * @param string $prefix
+ */
+ function _prepareTempTable($prefix, $drop_only = false)
+ {
+ $idfield = $this->Application->getUnitOption($prefix, 'IDField');
+ $table = $this->Application->getUnitOption($prefix,'TableName');
+ $temp_table = $this->Application->GetTempName($table);
+
+ $sql = 'DROP TABLE IF EXISTS %s';
+ $this->Conn->Query( sprintf($sql, $temp_table) );
+
+ if (!$drop_only) {
+ $sql = 'CREATE TABLE %s SELECT * FROM %s WHERE 0';
+ $this->Conn->Query( sprintf($sql, $temp_table, $table) );
+
+ $sql = 'ALTER TABLE %1$s CHANGE %2$s %2$s INT(11) NOT NULL';
+ $this->Conn->Query( sprintf($sql, $temp_table, $idfield) );
+ }
+
+ return $temp_table;
+ }
+
+ /**
+ * Prepares mapping between event name+type and their ids in database
+ *
+ */
+ function _updateEventsCache()
+ {
+ $sql = 'SELECT EventId, CONCAT(Event,"_",Type) AS EventMix
+ FROM ' . TABLE_PREFIX . 'Events';
+ $this->events_hash = $this->Conn->GetCol($sql, 'EventMix');
+ }
+
+ /**
+ * Processes parsed XML
+ *
+ * @param kXMLNode $language_node
+ */
+ function _processLanguages(&$language_node)
+ {
+ $field_mapping = Array (
+ 'DATEFORMAT' => 'DateFormat',
+ 'TIMEFORMAT' => 'TimeFormat',
+ 'INPUTDATEFORMAT' => 'InputDateFormat',
+ 'INPUTTIMEFORMAT' => 'InputTimeFormat',
+ 'DECIMAL' => 'DecimalPoint',
+ 'THOUSANDS' => 'ThousandSep',
+ 'CHARSET' => 'Charset',
+ 'UNITSYSTEM' => 'UnitSystem',
+ 'DOCS_URL' => 'UserDocsUrl',
+ );
+
+ do {
+ $language_id = false;
+
+ $fields_hash = Array (
+ 'PackName' => $language_node->Attributes['PACKNAME'],
+ 'LocalName' => $language_node->Attributes['PACKNAME'],
+ 'Encoding' => $language_node->Attributes['ENCODING'],
+ 'Charset' => 'iso-8859-1',
+ );
+
+ $sub_node =& $language_node->firstChild;
+ /* @var $sub_node kXMLNode */
+
+ do {
+ switch ($sub_node->Name) {
+ case 'PHRASES':
+ if ($sub_node->Children) {
+ if (!$language_id) {
+ $language_id = $this->_processLanguage($fields_hash);
+ }
+
+ if ($this->_debugMode) {
+ $start_time = getmicrotime();
+ }
+
+ $this->_processPhrases($sub_node->firstChild, $language_id, $fields_hash['Encoding']);
+
+ if ($this->_debugMode) {
+ $this->Application->Debugger->appendHTML(__CLASS__ . '::' . '_processPhrases: ' . (getmicrotime() - $start_time));
+ }
+ }
+ break;
+
+ case 'EVENTS':
+ if ($sub_node->Children) {
+ if (!$language_id) {
+ $language_id = $this->_processLanguage($fields_hash);
+ }
+
+ $this->_processEvents($sub_node->firstChild, $language_id, $fields_hash['Encoding']);
+ }
+ break;
+
+ default:
+ $fields_hash[ $field_mapping[$sub_node->Name] ] = $sub_node->Data;
+ break;
+ }
+ } while (($sub_node =& $sub_node->NextSibling()));
+ } while (($language_node =& $language_node->NextSibling()));
+ }
+
+ /**
+ * Performs phases import
+ *
+ * @param kXMLNode $phrase_node
+ * @param int $language_id
+ * @param string $language_encoding
+ */
+ function _processPhrases(&$phrase_node, $language_id, $language_encoding)
+ {
+ do {
+ $fields_hash = Array (
+ 'LanguageId' => $language_id,
+ 'Phrase' => $phrase_node->Attributes['LABEL'],
+ 'PhraseType' => $phrase_node->Attributes['TYPE'],
+ 'Module' => array_key_exists('MODULE', $phrase_node->Attributes) ? $phrase_node->Attributes['MODULE'] : 'Core',
+ 'LastChanged' => adodb_mktime(),
+ 'LastChangeIP' => $this->ip_address,
+ 'Translation' => $phrase_node->Data,
+ );
+
+ if (array_key_exists($fields_hash['PhraseType'], $this->phrase_types_allowed)) {
+ if ($language_encoding != 'plain') {
+ $fields_hash['Translation'] = base64_decode($fields_hash['Translation']);
+ }
+
+ $this->Conn->doInsert($fields_hash, $this->_tables['phrases'], 'INSERT', false);
+ }
+ } while (($phrase_node =& $phrase_node->NextSibling()));
+
+ $this->Conn->doInsert($fields_hash, $this->_tables['phrases'], 'INSERT');
+ }
+
+ /**
+ * Performs email event import
+ *
+ * @param kXMLNode $event_node
+ * @param int $language_id
+ * @param string $language_encoding
+ */
+ function _processEvents(&$event_node, $language_id, $language_encoding)
+ {
+ do {
+ $event_id = $this->_getEventId($event_node->Attributes['EVENT'], $event_node->Attributes['TYPE']);
+ if ($event_id) {
+ $fields_hash = Array (
+ 'LanguageId' => $language_id,
+ 'EventId' => $event_id,
+ 'MessageType' => $event_node->Attributes['MESSAGETYPE'],
+ );
+
+ if ($language_encoding == 'plain') {
+ $fields_hash['Template'] = rtrim($event_node->Data);
+ }
+ else {
+ $fields_hash['Template'] = base64_decode($event_node->Data);
+ }
+
+ $this->Conn->doInsert($fields_hash, $this->_tables['emailmessages'], 'INSERT', false);
+ }
+ } while (($event_node =& $event_node->NextSibling()));
+
+ $this->Conn->doInsert($fields_hash, $this->_tables['emailmessages'], 'INSERT');
+ }
+
+ /**
+ * Creates/updates language based on given fields and returns it's id
+ *
+ * @param Array $fields_hash
+ * @return int
+ */
+ function _processLanguage($fields_hash)
+ {
+ // 1. get language from database
+ $sql = 'SELECT ' . $this->lang_object->IDField . '
+ FROM ' . $this->lang_object->TableName . '
+ WHERE PackName = ' . $this->Conn->qstr($fields_hash['PackName']);
+ $language_id = $this->Conn->GetOne($sql);
+
+ if ($language_id) {
+ // 2. language found -> update, when allowed
+ $this->lang_object->Load($language_id);
+
+ if ($this->import_mode == LANG_OVERWRITE_EXISTING) {
+ // update live language record based on data from xml
+ $this->lang_object->SetFieldsFromHash($fields_hash);
+ $this->lang_object->Update();
+ }
+ }
+ else {
+ // 3. language not found -> create
+ $this->lang_object->SetFieldsFromHash($fields_hash);
+ $this->lang_object->SetDBField('Enabled', STATUS_ACTIVE);
+
+ if ($this->lang_object->Create()) {
+ $language_id = $this->lang_object->GetID();
+
+ if (defined('IS_INSTALL') && IS_INSTALL) {
+ // language created during install becomes admin interface language
+ $this->lang_object->setPrimary(true, true);
+ }
+ }
+ }
+
+ // 4. collect ID of every processed language
+ if (!in_array($language_id, $this->_languages)) {
+ $this->_languages[] = $language_id;
+ }
+
+ return $language_id;
+ }
+
+ /**
+ * Returns event id based on it's name and type
+ *
+ * @param string $event_name
+ * @param string $event_type
+ * @return int
+ */
+ function _getEventId($event_name, $event_type)
+ {
+ $cache_key = $event_name . '_' . $event_type;
+
+ return array_key_exists($cache_key, $this->events_hash) ? $this->events_hash[$cache_key] : 0;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/language_import_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.2.1
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/category_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/category_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/category_helper.php (revision 12306)
@@ -0,0 +1,477 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class CategoryHelper extends kHelper {
+
+ /**
+ * Structure tree for ParentId field in category or category items
+ *
+ * @var Array
+ */
+ var $_structureTree = null;
+
+ /**
+ * Prints category path using given blocks. Also supports used defined path elements at the end.
+ *
+ * @param Array $params
+ * @return string
+ */
+ function NavigationBar($params)
+ {
+ $main_category_id = isset($params['cat_id']) ? $params['cat_id'] : $this->Application->GetVar('m_cat_id');
+
+ $home_element = $this->getHomeCategoryPath($params, $main_category_id);
+ if (!getArrayValue($params, 'titles') && !getArrayValue($params, 'templates')) {
+ // no static templates given, show only category path
+ return $home_element . $this->getCategoryPath($main_category_id, $params);
+ }
+
+ $navigation_parts = $this->getNavigationParts($params['titles'], $params['templates']);
+
+ $ret = '';
+ $block_params = Array (); //$params; // sort of TagProcessor:prepareTagParams
+ $block_params['no_editing'] = 1;
+ $block_params['category'] = 0;
+ $block_params['separator'] = $params['separator'];
+ $current_template = $this->Application->GetVar('t');
+ $show_category = getArrayValue($params, 'show_category');
+
+ foreach ($navigation_parts as $template => $title) {
+ $block_params['template'] = $template;
+
+ if ($title == '__item__') {
+ if ($show_category) {
+ $ret .= $this->getCategoryPath($main_category_id, $params);
+ $show_category = false;
+ }
+
+ $category_path = $this->getCategoryParentPath($main_category_id);
+ $module_info = $this->getCategoryModule($params, array_keys($category_path));
+ if (!$module_info) {
+ continue;
+ }
+
+ $module_prefix = $module_info['Var'];
+ $object =& $this->Application->recallObject($module_prefix);
+ /* @var $object kCatDBItem */
+
+ $title_field = $this->Application->getUnitOption($module_prefix, 'TitleField');
+ $block_params['title'] = $object->GetField($title_field);
+ $block_params['prefix'] = $module_prefix;
+ $block_params['current'] = 0;
+
+ $block_params['name'] = $this->SelectParam($params, 'module_item_render_as,render_as');
+ }
+ else {
+ $block_params['current'] = ($template == $current_template);
+ $block_params['title'] = $this->Application->Phrase($title);
+
+ $block_params['name'] = $template == $current_template ? $params['current_render_as'] : $params['render_as'];
+ }
+
+ $ret .= $this->Application->ParseBlock($block_params);
+ }
+
+ if ($show_category) {
+ $params['no_current'] = true;
+ return $home_element . ($show_category ? $this->getCategoryPath($main_category_id, $params) : '') . $ret;
+ }
+
+ return $home_element . $ret;
+ }
+
+ /**
+ * Get navigation parts
+ *
+ * @param Array $titles
+ * @param Array $templates
+ * @return Array
+ */
+ function getNavigationParts($titles, $templates)
+ {
+ $titles = explode(',', $titles);
+ $templates = explode(',', $templates);
+
+ $ret = Array ();
+ foreach ($templates as $template_pos => $template) {
+ $ret[$template] = $titles[$template_pos];
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Renders path to given category using given blocks.
+ *
+ * @param int $main_category_id
+ * @param Array $params
+ * @return string
+ */
+ function getCategoryPath($main_category_id, $params)
+ {
+ $category_path = $this->getCategoryParentPath($main_category_id);
+ if (!$category_path) {
+ // in "Home" category
+ return '';
+ }
+
+ $module_info = $this->getCategoryModule($params, array_keys($category_path));
+
+ $module_category_id = $module_info['RootCat'];
+ $module_item_id = $this->Application->GetVar($module_info['Var'].'_id');
+
+ $ret = '';
+ $block_params['category'] = 1;
+ $block_params['no_editing'] = 1;
+ $block_params['separator'] = $params['separator'];
+ $no_current = isset($params['no_current']) && $params['no_current'];
+
+ $backup_category_id = $this->Application->GetVar('c_id');
+ foreach ($category_path as $category_id => $category_name) {
+ $block_params['cat_id'] = $category_id;
+ $block_params['cat_name'] = $block_params['title'] = $category_name;
+
+ if ($no_current) {
+ $block_params['current'] = 0;
+ }
+ else {
+ $block_params['current'] = ($main_category_id == $category_id) && !$module_item_id ? 1 : 0;
+ }
+
+ $block_params['is_module_root'] = $category_id == $module_category_id ? 1 : 0;
+ $block_params['name'] = $this->SelectParam($params, 'render_as,block');
+
+ // which block to parse as current ?
+ if ($block_params['is_module_root']) {
+ $block_params['name'] = $this->SelectParam($params, 'module_root_render_as,render_as');
+ $block_params['module_index'] = $module_info['TemplatePath'].'index';
+ }
+
+ if ($block_params['current']) {
+ $block_params['name'] = $this->SelectParam($params, 'current_render_as,render_as');
+ }
+
+ $this->Application->SetVar('c_id', $category_id);
+ $ret .= $this->Application->ParseBlock($block_params);
+ }
+ $this->Application->SetVar('c_id', $backup_category_id);
+
+ return $ret;
+ }
+
+ /**
+ * Returns module information based on given module name or current category (relative to module root categories)
+ *
+ * @param Array $params
+ * @param Array $category_ids category parent path (already as array)
+ * @return Array
+ */
+ function getCategoryModule($params, $category_ids)
+ {
+ if (isset($params['module'])) {
+ // get module by name specified
+ $module_info = $this->Application->findModule('Name', $params['module']);
+
+ }
+ elseif ($category_ids) {
+ // get module by category path
+ $module_root_categories = $this->getModuleRootCategories();
+ $common_categories = array_intersect($category_ids, $module_root_categories);
+ $module_category_id = array_shift($common_categories); // get 1st common category
+ $module_info = $this->Application->findModule('RootCat', $module_category_id);
+ }
+
+ return $module_info;
+ }
+
+ /**
+ * Renders path to top catalog category
+ *
+ * @param Array $params
+ * @param int $current_category
+ * @return string
+ */
+ function getHomeCategoryPath($params, $current_category)
+ {
+ $block_params['cat_id'] = $this->Application->findModule('Name', 'Core', 'RootCat'); // 0;
+ $block_params['no_editing'] = 1;
+ $block_params['current'] = $current_category == $block_params['cat_id'] ? 1 : 0;
+ $block_params['separator'] = $params['separator'];
+ $block_params['cat_name'] = $this->Application->ProcessParsedTag('m', 'RootCategoryName', $params);
+ $block_params['name'] = $this->SelectParam($params, 'root_cat_render_as,render_as');
+ return $this->Application->ParseBlock($block_params);
+ }
+
+ /**
+ * Returns root categories from all modules
+ *
+ * @return Array
+ */
+ function getModuleRootCategories()
+ {
+ static $root_categories = null;
+
+ if (!isset($root_categories)) {
+ $root_categories = Array ();
+ foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
+ array_push($root_categories, $module_info['RootCat']);
+ }
+
+ $root_categories = array_unique($root_categories);
+ }
+
+ return $root_categories;
+ }
+
+ /**
+ * Returns given category's parent path as array of id=>name elements
+ *
+ * @param int $main_category_id
+ * @return Array
+ */
+ function getCategoryParentPath($main_category_id)
+ {
+ static $cached_path = null;
+
+ if ($main_category_id == 0) {
+ // don't query path for "Home" category
+ return Array ();
+ }
+
+ if (!isset($cached_path[$main_category_id])) {
+ $ml_formatter =& $this->Application->recallObject('kMultiLanguage');
+ $navbar_field = $ml_formatter->LangFieldName('CachedNavBar');
+
+ $id_field = $this->Application->getUnitOption('c', 'IDField');
+ $table_name = $this->Application->getUnitOption('c', 'TableName');
+
+ $sql = 'SELECT '.$navbar_field.', ParentPath
+ FROM '.$table_name.'
+ WHERE '.$id_field.' = '.$main_category_id;
+ $category_data = $this->Conn->GetRow($sql);
+
+ $skip_category = $this->Application->findModule('Name', 'Core', 'RootCat');
+ $cached_path[$main_category_id] = Array ();
+ if ($category_data) {
+ $category_names = explode('&|&', $category_data[$navbar_field]);
+ $category_ids = explode('|', substr($category_data['ParentPath'], 1, -1));
+
+ foreach ($category_ids as $category_index => $category_id) {
+ if ($category_id == $skip_category) {
+ continue;
+ }
+ $cached_path[$main_category_id][$category_id] = $category_names[$category_index];
+ }
+ }
+ }
+ return $cached_path[$main_category_id];
+ }
+
+ /**
+ * Not tag, method for parameter
+ * selection from list in this TagProcessor
+ *
+ * @param Array $params
+ * @param string $possible_names
+ * @return string
+ * @access public
+ */
+ function SelectParam($params, $possible_names)
+ {
+ if (!is_array($params)) return;
+ if (!is_array($possible_names))
+
+ $possible_names = explode(',', $possible_names);
+ foreach ($possible_names as $name)
+ {
+ if( isset($params[$name]) ) return $params[$name];
+ }
+ return false;
+ }
+
+ /**
+ * Converts multi-dimensional category structure in one-dimensional option array (category_id=>category_name)
+ *
+ * @param Array $data
+ * @param int $parent_category_id
+ * @param int_type $language_id
+ * @param int $theme_id
+ * @param int $level
+ * @return Array
+ */
+ function _printChildren(&$data, $parent_category_id, $language_id, $theme_id, $level = 0)
+ {
+ if ($data['ThemeId'] != $theme_id && $data['ThemeId'] != 0) {
+ // don't show system templates from different themes
+ return Array ();
+ }
+
+ $ret = Array($parent_category_id => str_repeat('-', $level).' '.$data['l'.$language_id.'_Name']);
+
+ if ($data['children']) {
+ $level++;
+ foreach ($data['children'] as $category_id => $category_data) {
+ $ret = array_merge_recursive2($ret, $this->_printChildren($data['children'][$category_id], $category_id, $language_id, $theme_id, $level));
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Returns information about children under parent path (recursive)
+ *
+ * @param int $parent_category_id
+ * @param int $language_count
+ * @return Array
+ */
+ function _getChildren($parent_category_id, $language_count)
+ {
+ $id_field = $this->Application->getUnitOption('c', 'IDField');
+
+ // get category children + parent category
+ $sql = 'SELECT *
+ FROM '.$this->Application->getUnitOption('c', 'TableName').'
+ WHERE ParentId = '.$parent_category_id.' OR '.$id_field.' = '.$parent_category_id.'
+ ORDER BY Priority DESC';
+ $categories = $this->Conn->Query($sql, $id_field);
+
+ $parent_data = $categories[$parent_category_id];
+ unset($categories[$parent_category_id]);
+
+ // no children for this category
+ $data = Array ('id' => $parent_data[$id_field], 'children' => false, 'ThemeId' => $parent_data['ThemeId']);
+ for ($i = 1; $i <= $language_count; $i++) {
+ $data['l'.$i.'_Name'] = $parent_data['l'.$i.'_Name'];
+ }
+
+ if (!$categories) {
+ // no children
+ return $data;
+ }
+
+ // category has children
+ foreach ($categories as $category_id => $category_data) {
+ $data['children'][$category_id] = $this->_getChildren($category_id, $language_count);
+ }
+
+ return $data;
+ }
+
+ /**
+ * Generates OR retrieves from cache structure tree
+ *
+ * @return Array
+ */
+ function &_getStructureTree()
+ {
+ // get cached version of structure tree
+ $sql = 'SELECT Data
+ FROM ' . TABLE_PREFIX . 'Cache
+ WHERE VarName = "StructureTree"';
+ $data = $this->Conn->GetOne($sql);
+
+ if ($data) {
+ $data = unserialize($data);
+
+ return $data;
+ }
+
+ // generate structure tree from scratch
+ $ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
+ /* @var $ml_helper kMultiLanguageHelper */
+
+ $language_count = $ml_helper->getLanguageCount();
+
+ $root_category = $this->Application->findModule('Name', 'Core', 'RootCat');
+ $data = $this->_getChildren($root_category, $language_count);
+
+ $fields_hash = Array (
+ 'VarName' => 'StructureTree',
+ 'Data' => serialize($data),
+ 'Cached' => adodb_mktime(),
+ );
+
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'Cache', 'REPLACE');
+
+ return $data;
+ }
+
+ /**
+ * Returns category structure as field option list
+ *
+ * @return Array
+ */
+ function getStructureTreeAsOptions()
+ {
+ if (defined('IS_INSTALL') && IS_INSTALL) {
+ // no need to create category structure during install, because it's not used there
+ return Array ();
+ }
+
+ if (isset($this->_structureTree)) {
+ return $this->_structureTree;
+ }
+
+ $themes_helper =& $this->Application->recallObject('ThemesHelper');
+ /* @var $themes_helper kThemesHelper */
+
+ $data = $this->_getStructureTree();
+
+ $theme_id = (int)$themes_helper->getCurrentThemeId();
+ $root_category = $this->Application->findModule('Name', 'Core', 'RootCat');
+
+ $this->_structureTree = $this->_printChildren($data, $root_category, $this->Application->GetVar('m_lang'), $theme_id);
+
+ return $this->_structureTree;
+ }
+
+ /**
+ * Replace links like "@@ID@@" to actual template names in given text
+ *
+ * @param string $text
+ * @return string
+ */
+ function replacePageIds($text)
+ {
+ if (!preg_match_all('/@@(\\d+)@@/', $text, $regs)) {
+ return $text;
+ }
+
+ $page_ids = $regs[1];
+
+ $sql = 'SELECT NamedParentPath, CategoryId
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId IN (' . implode(',', $page_ids) . ')';
+ $templates = $this->Conn->GetCol($sql, 'CategoryId');
+
+ foreach ($page_ids as $page_id) {
+ if (!array_key_exists($page_id, $templates)) {
+ // internal page was deleted, but link to it was found in given content block data
+ continue;
+ }
+
+ $url_params = Array ('m_cat_id' => $page_id, 'pass' => 'm');
+ $page_url = $this->Application->HREF(strtolower($templates[$page_id]), '', $url_params);
+ /*if ($this->Application->IsAdmin()) {
+ $page_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $page_url);
+ }*/
+ $text = preg_replace('/@@' . $page_id . '@@/', $page_url, $text);
+ }
+
+ return $text;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/category_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.3.2.7
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/controls/minput_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/controls/minput_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/controls/minput_helper.php (revision 12306)
@@ -0,0 +1,197 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class MInputHelper extends kHelper {
+
+
+ /**
+ * Returns user education table name
+ *
+ * @param kDBItem $object
+ * @return string
+ */
+ function getTable($prefix, $temp=false)
+ {
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+ return $temp ? $this->Application->GetTempName($table_name, 'prefix:'.$prefix) : $table_name;
+ }
+
+ function prepareMInputXML($records, $use_fields)
+ {
+ $xml = '';
+ foreach ($records as $record) {
+ $xml .= '<record>';
+ foreach ($record as $field_name => $field_value) {
+ if (!in_array($field_name, $use_fields)) {
+ continue;
+ }
+ $xml .= '<field name="' . $field_name . '">' . htmlspecialchars($field_value) . '</field>';
+ }
+ $xml .= '</record>';
+ }
+
+ return $xml ? '<records>'.$xml.'</records>' : '';
+ }
+
+ function prepareErrorsXML(&$object, $fields_hash)
+ {
+ $xml = '';
+ foreach ($fields_hash as $field_name => $field_value) {
+ $object->SetField($field_name, $field_value);
+ if (!$object->ValidateField($field_name)) {
+ $xml .= '<field name="'.$field_name.'">'.$object->GetErrorMsg($field_name, false).'</field>';
+ }
+ }
+
+ return '<errors>'.$xml.'</errors>';
+ }
+
+ /**
+ * Validates MInput control fields
+ *
+ * @param kEvent $event
+ */
+ function OnValidateMInputFields(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
+ if ($items_info) {
+ list ($id, $field_values) = each($items_info);
+
+ echo $this->prepareErrorsXML($object, $field_values);
+ }
+
+ $event->status = erSTOP;
+ }
+
+ function parseMInputXML($xml)
+ {
+ $xml_helper =& $this->Application->recallObject('kXMLHelper');
+ /* @var $xml_helper kXMLHelper */
+
+ $root_node =& $xml_helper->Parse($xml);
+ $root_node =& $root_node->FindChild('records');
+ if (!$root_node || !$root_node->firstChild) {
+ return false;
+ }
+
+ $records = Array ();
+ $current_node = $root_node->firstChild;
+ /* @var $current_node kXMLNode */
+
+ do {
+ $record = Array();
+ $sub_node =& $current_node->firstChild;
+ /* @var $current_node kXMLNode */
+
+ do {
+ $record[$sub_node->Attributes['NAME']] = $sub_node->Data;
+
+ }while ( ($sub_node =& $sub_node->NextSibling()) );
+
+ $records[] = $record;
+ } while (($current_node =& $current_node->NextSibling()));
+
+ return $records;
+ }
+
+ /**
+ * Loads selected values from sub_prefix to main item virtual field.
+ * Called from OnAfterItemLoad of main prefix.
+ *
+ * @param kEvent $event
+ * @param string $store_field main item's field name, to store values into
+ * @param string $sub_prefix prefix used to store info about selected items
+ * @param Array $use_fields fields, used in value string building
+ */
+ function LoadValues(&$event, $store_field, $sub_prefix, $use_fields)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $sub_item =& $this->Application->recallObject($sub_prefix, null, Array('skip_autoload' => true));
+ /* @var $sub_item kDBItem */
+
+ $foreign_key = $this->Application->getUnitOption($sub_prefix, 'ForeignKey');
+
+ $sql = 'SELECT *
+ FROM '.$this->getTable($sub_prefix, $object->IsTempTable()).'
+ WHERE '.$foreign_key.' = '.$object->GetID();
+
+ $selected_items = $this->Conn->Query($sql);
+
+ $field_names = array_keys( $sub_item->GetFieldValues() );
+
+ foreach ($selected_items as $key => $fields_hash) {
+ $sub_item->Clear();
+ $sub_item->SetDBFieldsFromHash($fields_hash);
+
+ // to fill *_date and *_time fields from main date fields
+ $sub_item->UpdateFormattersSubFields();
+
+ foreach ($field_names as $field) {
+ $field_options = $sub_item->GetFieldOptions($field);
+ $formatter = array_key_exists('formatter', $field_options) ? $field_options['formatter'] : false;
+
+ if ($formatter == 'kDateFormatter') {
+ $selected_items[$key][$field] = $sub_item->GetField($field, $field_options['input_format']);
+ }
+ else {
+ $selected_items[$key][$field] = $sub_item->GetDBField($field);
+ }
+ }
+ }
+
+ $object->SetDBField($store_field, $this->prepareMInputXML($selected_items, $use_fields));
+ }
+
+ /**
+ * Saves data from minput control to subitem table (used from subitem hook)
+ *
+ * @param kEvent $sub_event
+ * @param string $store_field
+ */
+ function SaveValues(&$sub_event, $store_field)
+ {
+ $main_object =& $sub_event->MasterEvent->getObject();
+ $affected_field = $main_object->GetDBField($store_field);
+
+ $object =& $this->Application->recallObject($sub_event->getPrefixSpecial(), null, Array('skip_autoload' => true));
+ /*@var $object kDBItem*/
+
+ $sub_table = $object->TableName;
+ $foreign_key = $this->Application->getUnitOption($sub_event->Prefix, 'ForeignKey');
+
+ $sql = 'DELETE FROM '.$sub_table.'
+ WHERE '.$foreign_key.' = '.$main_object->GetID();
+
+ $this->Conn->Query($sql);
+
+ if ($affected_field) {
+ $records = $this->parseMInputXML($affected_field);
+ $main_id = $main_object->GetID();
+
+ foreach ($records as $fields_hash) {
+ $object->Clear();
+ $fields_hash[$foreign_key] = $main_id;
+ $object->SetDBFieldsFromHash($fields_hash);
+ $object->Create();
+ }
+ }
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/controls/minput_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.8.4
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/controls/edit_picker_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/controls/edit_picker_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/controls/edit_picker_helper.php (revision 12306)
@@ -0,0 +1,181 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class EditPickerHelper extends kHelper {
+
+
+ function getTable($prefix, $temp=false)
+ {
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+ return $temp ? $this->Application->GetTempName($table_name, 'prefix:'.$prefix) : $table_name;
+ }
+
+ /**
+ * Applies filter for multiple lists in inp_edit_picker control.
+ * Called from SetCustomQuery of prefix, that contains all available items.
+ *
+ * @param kEvent $event
+ * @param string $storage_field main item's field name, where values are located
+ */
+ function applyFilter(&$event, $storage_field)
+ {
+ if ($event->Special != 'selected' && $event->Special != 'available') {
+ return ;
+ }
+
+ if ($storage_field != $event->getEventParam('link_to_field')) {
+ return ;
+ }
+
+ $object =& $event->getObject();
+ /* @var $object kDBList */
+
+ $main_object =& $this->Application->recallObject($event->getEventParam('link_to_prefix'));
+ /* @var $main_object kDBItem */
+
+ $selected_items = $main_object->GetDBField($storage_field);
+ if ($selected_items) {
+ $filter_type = $event->Special == 'selected' ? 'IN' : 'NOT IN';
+ $selected_items = explode('|', substr($selected_items, 1, -1));
+ $filter_clause = '%1$s.' . $object->IDField.' '.$filter_type.' ('.implode(',', $selected_items).')';
+ }
+ else {
+ $filter_clause = ($event->Special == 'selected') ? 'FALSE' : 'TRUE';
+ }
+
+ $constrain = $this->_getConstrain($main_object, $storage_field, 'filter');
+ if ($constrain) {
+ $filter_clause .= ' AND (' . $constrain . ')';
+ }
+
+ $object->addFilter('edit_picker_filter', $filter_clause);
+ }
+
+ /**
+ * Loads selected values from sub_prefix to main item virtual field.
+ * Called from OnAfterItemLoad of main prefix.
+ *
+ * @param kEvent $event
+ * @param string $store_field main item's field name, to store values into
+ * @param string $source_field prefix and it's field used to store info about selected items (format: prefix.field)
+ */
+ function LoadValues(&$event, $store_field, $source_field)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ list ($sub_prefix, $sub_prefix_field) = explode('.', $source_field);
+ $foreign_key = $this->Application->getUnitOption($sub_prefix, 'ForeignKey');
+
+ $sql = 'SELECT '.$sub_prefix_field.'
+ FROM '.$this->getTable($sub_prefix, $object->IsTempTable()).'
+ WHERE '.$foreign_key.' = '.$object->GetID();
+
+ $constrain = $this->_getConstrain($object, $store_field, 'load');
+ if ($constrain) {
+ $sql .= ' AND (' . $sub_prefix_field . ' IN (' . $constrain . '))';
+ }
+
+ $selected_items = array_unique($this->Conn->GetCol($sql));
+
+ $object->SetDBField($store_field, $selected_items ? '|'.implode('|', $selected_items).'|' : '');
+ }
+
+ /**
+ * Saves value to subitem's table
+ *
+ * @param kEvent $sub_event
+ * @param string $store_field main item's field name, to get values from
+ * @param string $sub_prefix_field check already existing records by this field
+ */
+ function SaveValues(&$sub_event, $store_field, $sub_prefix_field)
+ {
+ $main_object =& $sub_event->MasterEvent->getObject();
+ /* @var $main_object kDBItem */
+
+ $affected_field = $main_object->GetDBField($store_field);
+
+ $object =& $this->Application->recallObject($sub_event->getPrefixSpecial(), null, Array('skip_autoload' => true));
+ /* @var $object kDBItem */
+
+ $sub_table = $object->TableName;
+ $foreign_key = $this->Application->getUnitOption($sub_event->Prefix, 'ForeignKey');
+
+ // 1. get previous values from db
+ $sql = 'SELECT ' . $sub_prefix_field . '
+ FROM ' . $sub_table . '
+ WHERE '.$foreign_key.' = '.$main_object->GetID();
+
+ $constrain = $this->_getConstrain($main_object, $store_field, 'save');
+ if ($constrain) {
+ $sql .= ' AND (' . $sub_prefix_field . ' IN (' . $constrain . '))';
+ }
+
+ $old_values = $this->Conn->GetCol($sql);
+
+ // 2. get new values from form
+ $new_values = $affected_field ? explode('|', substr($affected_field, 1, -1)) : Array ();
+
+ $records_to_add = array_diff($new_values, $old_values);
+ $records_to_delete = array_diff($old_values, $new_values);
+
+ if ($records_to_delete && $main_object->Loaded) {
+ $where_clause = Array (
+ $foreign_key . ' = ' . $main_object->GetID(),
+ $sub_prefix_field . ' IN (' . implode(',', $records_to_delete) . ')',
+ );
+ $sql = 'SELECT ' . $object->IDField . '
+ FROM ' . $sub_table . '
+ WHERE (' . implode(') AND (', $where_clause) . ')';
+ $delete_ids = $this->Conn->GetCol($sql);
+
+ foreach ($delete_ids as $delete_id) {
+ $object->Delete($delete_id);
+ }
+ }
+
+ if ($records_to_add) {
+ $main_id = $main_object->GetID();
+ foreach ($records_to_add as $add_id) {
+ $object->Clear();
+ $object->SetDBField($foreign_key, $main_id);
+ $object->SetDBField($sub_prefix_field, $add_id);
+ $object->Create();
+
+ if ($object->IsTempTable()) {
+ $object->setTempID();
+ }
+ }
+ }
+ }
+
+ function _getConstrain(&$object, $store_field, $mode = 'filter')
+ {
+ $field_options = $object->GetFieldOptions($store_field);
+ $constrain = array_key_exists('option_constrain', $field_options) ? $field_options['option_constrain'] : false;
+
+ if ($mode == 'filter') {
+ // filter on edit form
+ return $constrain;
+ }
+ elseif ($constrain) {
+ // load or save
+ return sprintf($field_options['options_sql'], $field_options['option_key_field']);
+ }
+
+ return false;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/controls/edit_picker_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.8.5
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/controls/controls_config.php
===================================================================
--- branches/5.0.x/core/units/helpers/controls/controls_config.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/controls/controls_config.php (revision 12306)
@@ -0,0 +1,25 @@
+<?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.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+ $config = Array(
+ 'Prefix' => 'control-helpers',
+ 'EventHandlerClass' => Array('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'),
+
+ 'RegisterClasses' => Array(
+ Array('pseudo'=>'MInputHelper','class'=>'MInputHelper','file'=>'minput_helper.php','build_event'=>'','require_classes'=>'kHelper'),
+ Array('pseudo' => 'EditPickerHelper', 'class' => 'EditPickerHelper', 'file' => 'edit_picker_helper.php', 'build_event' => '', 'require_classes' => Array('kHelper')),
+ ),
+ );
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/controls/controls_config.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.8.1
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/file_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/file_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/file_helper.php (revision 12306)
@@ -0,0 +1,233 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class FileHelper extends kHelper {
+
+ /**
+ * Puts existing item images (from subitem) to virtual fields (in main item)
+ *
+ * @param kCatDBItem $object
+ */
+ function LoadItemFiles(&$object)
+ {
+ $max_file_count = $this->Application->ConfigValue($object->Prefix.'_MaxImageCount'); // file count equals to image count (temporary measure)
+
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'ItemFiles
+ WHERE ResourceId = '.$object->GetDBField('ResourceId').'
+ ORDER BY FileId ASC
+ LIMIT 0, '.(int)$max_file_count;
+ $item_files = $this->Conn->Query($sql);
+
+ $file_counter = 1;
+ foreach ($item_files as $item_file) {
+ $file_path = $item_file['FilePath'];
+ $object->SetDBField('File'.$file_counter, $file_path);
+ $object->SetOriginalField('File'.$file_counter, $file_path);
+ $object->Fields['File'.$file_counter]['original_field'] = $item_file['FileName'];
+ $file_counter++;
+ }
+ }
+
+ /**
+ * Saves newly uploaded images to external image table
+ *
+ * @param kCatDBItem $object
+ */
+ function SaveItemFiles(&$object)
+ {
+ $table_name = $this->Application->getUnitOption('#file', 'TableName');
+ $max_file_count = $this->Application->getUnitOption($object->Prefix, 'FileCount'); // $this->Application->ConfigValue($object->Prefix.'_MaxImageCount');
+
+ $i = 0;
+ while ($i < $max_file_count) {
+ $field = 'File'.($i + 1);
+ $field_options = $object->GetFieldOptions($field);
+
+ $file_path = $object->GetDBField($field);
+ if ($file_path) {
+ if (isset($field_options['original_field'])) {
+ $key_clause = 'FileName = '.$this->Conn->qstr($field_options['original_field']).' AND ResourceId = '.$object->GetDBField('ResourceId');
+
+ if ($object->GetDBField('Delete'.$field)) {
+ // if item was cloned, then new filename is in db (not in $image_src)
+ $sql = 'SELECT FilePath
+ FROM '.$table_name.'
+ WHERE '.$key_clause;
+ $file_path = $this->Conn->GetOne($sql);
+ if (@unlink(FULL_PATH.ITEM_FILES_PATH.$file_path)) {
+ $sql = 'DELETE FROM '.$table_name.'
+ WHERE '.$key_clause;
+ $this->Conn->Query($sql);
+ }
+ }
+ else {
+ // image record found -> update
+ $fields_hash = Array (
+ 'FilePath' => $file_path,
+ );
+
+ $this->Conn->doUpdate($fields_hash, $table_name, $key_clause);
+ }
+ }
+ else {
+ // record not found -> create
+ $fields_hash = Array (
+ 'ResourceId' => $object->GetDBField('ResourceId'),
+ 'FileName' => $field,
+ 'Status' => STATUS_ACTIVE,
+ 'FilePath' => $file_path,
+ );
+
+ $this->Conn->doInsert($fields_hash, $table_name);
+ $field_options['original_field'] = $field;
+ $object->SetFieldOptions($field, $field_options);
+ }
+ }
+ $i++;
+ }
+ }
+
+ /**
+ * Preserves cloned item images/files to be rewrited with original item images/files
+ *
+ * @param Array $field_values
+ */
+ function PreserveItemFiles(&$field_values)
+ {
+ foreach ($field_values as $field_name => $field_value) {
+ if (!is_array($field_value)) continue;
+
+ if (isset($field_value['upload']) && ($field_value['error'] == UPLOAD_ERR_NO_FILE)) {
+ // this is upload field, but nothing was uploaded this time
+ unset($field_values[$field_name]);
+ }
+ }
+ }
+
+ /**
+ * Determines what image/file fields should be created (from post or just dummy fields for 1st upload)
+ *
+ * @param string $prefix
+ * @param bool $is_image
+ */
+ function createItemFiles($prefix, $is_image = false)
+ {
+ $items_info = $this->Application->GetVar($prefix);
+ if ($items_info) {
+ list ($id, $fields_values) = each($items_info);
+ $this->createUploadFields($prefix, $fields_values, $is_image);
+ }
+ else {
+ $this->createUploadFields($prefix, Array(), $is_image);
+ }
+ }
+
+ /**
+ * Dynamically creates virtual fields for item for each image/file field in submit
+ *
+ * @param string $prefix
+ * @param Array $fields_values
+ * @param bool $is_image
+ */
+ function createUploadFields($prefix, $fields_values, $is_image = false)
+ {
+ $field_options = Array (
+ 'type' => 'string',
+ 'max_len' => 240,
+ 'default' => '',
+ 'not_null' => 1,
+ );
+
+ if ($is_image) {
+ $field_options['formatter'] = 'kPictureFormatter';
+ $field_options['include_path'] = 1;
+ $field_options['allowed_types'] = Array ('image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png', 'image/gif', 'image/bmp');
+ $field_prefix = 'Image';
+ }
+ else {
+ $field_options['formatter'] = 'kUploadFormatter';
+ $field_options['upload_dir'] = ITEM_FILES_PATH;
+ $field_options['allowed_types'] = Array ('application/pdf', 'application/msexcel', 'application/msword', 'application/mspowerpoint');
+ $field_prefix = 'File';
+ }
+
+ $fields = $this->Application->getUnitOption($prefix, 'Fields');
+ $virtual_fields = $this->Application->getUnitOption($prefix, 'VirtualFields');
+
+ $image_count = 0;
+ foreach ($fields_values as $field_name => $field_value) {
+ if (preg_match('/^('.$field_prefix.'[\d]+|Primary'.$field_prefix.')$/', $field_name)) {
+ $fields[$field_name] = $field_options;
+ $virtual_fields[$field_name] = $field_options;
+ $this->_createCustomFields($prefix, $field_name, $virtual_fields, $is_image);
+
+ $image_count++;
+ }
+ }
+
+ if (!$image_count) {
+ // no images found in POST -> create default image fields
+ $image_names = Array ('Primary'.$field_prefix => '');
+ $image_count = $this->Application->ConfigValue($prefix.'_MaxImageCount');
+
+ $created_count = 1;
+ while ($created_count < $image_count) {
+ $image_names[$field_prefix.$created_count] = '';
+ $created_count++;
+ }
+
+ $this->createUploadFields($prefix, $image_names, $is_image);
+ return ;
+ }
+
+ $this->Application->setUnitOption($prefix, $field_prefix.'Count', $image_count);
+ $this->Application->setUnitOption($prefix, 'Fields', $fields);
+ $this->Application->setUnitOption($prefix, 'VirtualFields', $virtual_fields);
+ }
+
+ /**
+ * Adds ability to create more virtual fields associated with main image/file
+ *
+ * @param string $prefix
+ * @param string $field_name
+ * @param Array $virtual_fields
+ */
+ function _createCustomFields($prefix, $field_name, &$virtual_fields, $is_image)
+ {
+ $virtual_fields['Delete' . $field_name] = Array ('type' => 'int', 'not_null' => 1, 'default' => 0);
+
+ if ($is_image) {
+ $virtual_fields[$field_name . 'Alt'] = Array ('type' => 'string', 'default' => '');
+ }
+ }
+
+ /**
+ * Downloads file to user
+ *
+ * @param string $filename
+ */
+ function DownloadFile($filename)
+ {
+ $content_type = function_exists('mime_content_type') ? mime_content_type($filename) : 'application/octet-stream';
+
+ header('Content-type: '.$content_type);
+ header('Content-Disposition: attachment; filename="'.basename($filename).'"');
+ header('Content-Length: '.filesize($filename));
+ readfile($filename);
+ flush();
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/file_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.2.2
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/mod_rewrite_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/mod_rewrite_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/mod_rewrite_helper.php (revision 12306)
@@ -0,0 +1,921 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kModRewriteHelper extends kHelper {
+
+ /**
+ * Holds a refererence to httpquery
+ *
+ * @var kHttpQuery
+ */
+ var $HTTPQuery = null;
+
+ /**
+ * Parts found during url parsing
+ *
+ * @var Array
+ */
+ var $_partsFound = Array ();
+
+ /**
+ * Category item prefix, that was found
+ *
+ * @var string
+ */
+ var $_modulePrefix = false;
+
+ /**
+ * Constructor of kModRewriteHelper class
+ *
+ * @return kModRewriteHelper
+ */
+ function kModRewriteHelper()
+ {
+ parent::kHelper();
+
+ $this->HTTPQuery =& $this->Application->recallObject('HTTPQuery');
+ }
+
+ 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 {
+ $vars = $this->parseRewriteURL($url);
+ $passed = $vars['pass']; // also used in bottom of this method
+ unset($vars['pass']);
+
+ $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 parseRewriteURL($url)
+ {
+ $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 ('pass' => Array ('m'));
+ $url_parts = $url ? explode('/', trim($url, '/')) : Array ();
+
+ if (($this->HTTPQuery->Get('rewrite') == 'on') || !$url_parts) {
+ $this->_setDefaultValues($vars);
+ }
+
+ if (!$url_parts) {
+ $this->InitAll();
+ $vars['t'] = $this->HTTPQuery->getDefaultTemplate('');
+
+ return $vars;
+ }
+ else {
+ $vars['t'] = '';
+ }
+
+ $this->_parseLanguage($url_parts, $vars);
+ $this->_parseTheme($url_parts, $vars);
+ $this->_setDefaultPages($vars);
+
+ if ($this->_parsePage($url_parts, $vars)) {
+ $this->_partsFound[] = 'parsePage';
+ }
+
+ // 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)
+ // http://site-url/<language>/<theme>/<rl_injections>/<category>[_<category_page>]/<rl_part> (customized url)
+
+ if ( $this->processRewriteListeners($url_parts, $vars) ) {
+ return $vars;
+ }
+
+ if ($this->_parsePhisycalTemplate($url_parts, $vars)) {
+ $this->_partsFound[] = 'parsePhisycalTemplate';
+ }
+
+ if (($this->_modulePrefix === false) && in_array('parseCategory', $this->_partsFound)) {
+ // no item found, but category found -> module index page
+ foreach ($this->Application->ModuleInfo as $module_name => $info) {
+ // no idea what module we are talking about, so pass info form all modules
+ $vars['pass'][] = $info['Var'];
+ }
+
+ return $vars;
+ }
+
+ if (!$this->_partsFound) {
+ $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;
+ }
+
+ function InitAll()
+ {
+ $this->Application->VerifyLanguageId();
+ $this->Application->Phrases->Init('phrases');
+ $this->Application->VerifyThemeId();
+ }
+
+ /**
+ * Processes url using rewrite listeners
+ *
+ * @param Array $url_parts
+ * @param Array $vars
+ * @return bool
+ */
+ function processRewriteListeners(&$url_parts, &$vars)
+ {
+ $this->initRewriteListeners();
+
+ foreach ($this->Application->RewriteListeners as $prefix => $listener) {
+ $listener_result = $listener[0]->$listener[1](REWRITE_MODE_PARSE, $prefix, $vars, $url_parts);
+ if ($listener_result === false) {
+ // will not proceed to other methods
+ return true;
+ }
+ }
+
+ // will proceed to other methods
+ return false;
+ }
+
+ /**
+ * Parses real template name from url
+ *
+ * @param Array $url_parts
+ * @param Array $vars
+ * @return bool
+ */
+ function _parsePhisycalTemplate($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;
+ }
+
+ /**
+ * Parses category part of url, build main part of url
+ *
+ * @param int $rewrite_mode Mode in what rewrite listener was called. Possbile two modes: REWRITE_MODE_BUILD, REWRITE_MODE_PARSE.
+ * @param string $prefix Prefix, that listener uses for system integration
+ * @param Array $params Params, that are used for url building or created during url parsing.
+ * @param Array $url_parts Url parts to parse (only for parsing).
+ * @param bool $keep_events Keep event names in resulting url (only for building).
+ * @return bool|string|Array Return true to continue to next listener; return false (when building) not to rewrite given prefix; return false (when parsing) to stop processing at this listener.
+ */
+ function MainRewriteListener($rewrite_mode = REWRITE_MODE_BUILD, $prefix, &$params, &$url_parts, $keep_events = false)
+ {
+ if ($rewrite_mode == REWRITE_MODE_BUILD) {
+ return $this->_buildMainUrl($prefix, $params, $keep_events);
+ }
+
+ if ( $this->_parseFriendlyUrl($url_parts, $params) ) {
+ // friendly urls work like exact match only!
+ return false;
+ }
+
+ if ($this->_parseCategory($url_parts, $params)) {
+ $this->_partsFound[] = 'parseCategory';
+ }
+
+ return true;
+ }
+
+ /**
+ * Build main part of every url
+ *
+ * @param string $prefix_special
+ * @param Array $params
+ * @param bool $keep_events
+ * @return string
+ */
+ function _buildMainUrl($prefix_special, &$params, $keep_events)
+ {
+ $ret = '';
+ list ($prefix) = explode('.', $prefix_special);
+
+ $processed_params = $this->getProcessedParams($prefix_special, $params, $keep_events);
+ if ($processed_params === false) {
+ return '';
+ }
+
+ // add language
+ $default_language_id = $this->Application->GetDefaultLanguageId();
+ if ($processed_params['m_lang'] && ($processed_params['m_lang'] != $default_language_id)) {
+ $language_name = $this->Application->getCache('language_names', $processed_params['m_lang']);
+ if ($language_name === false) {
+ $sql = 'SELECT PackName
+ FROM ' . TABLE_PREFIX . 'Language
+ WHERE LanguageId = ' . $processed_params['m_lang'];
+ $language_name = $this->Conn->GetOne($sql);
+
+ $this->Application->setCache('language_names', $processed_params['m_lang'], $language_name);
+ }
+
+ $ret .= $language_name . '/';
+ }
+
+ // add theme
+ $default_theme_id = $this->Application->GetDefaultThemeId();
+ if ($processed_params['m_theme'] && ($processed_params['m_theme'] != $default_theme_id)) {
+ $theme_name = $this->Application->getCache('theme_names', $processed_params['m_theme']);
+ if ($theme_name === false) {
+ $sql = 'SELECT Name
+ FROM ' . TABLE_PREFIX . 'Theme
+ WHERE ThemeId = ' . $processed_params['m_theme'];
+ $theme_name = $this->Conn->GetOne($sql);
+
+ $this->Application->setCache('theme_names', $processed_params['m_theme'], $theme_name);
+
+ }
+
+ $ret .= $theme_name . '/';
+ }
+
+ // inject custom url parts made by other rewrite listeners just after language/theme url parts
+ $ret .= implode('/', $params['inject_parts']) . '/';
+
+ // add category
+ if ($processed_params['m_cat_id'] > 0 && $params['pass_category']) {
+ $category_filename = $this->Application->getFilename('c', $processed_params['m_cat_id']);
+
+ preg_match('/^Content\/(.*)/i', $category_filename, $regs);
+
+ if ($regs) {
+ $template = array_key_exists('t', $params) ? $params['t'] : false;
+
+ if (strtolower($regs[1]) == strtolower($template)) {
+ // we could have category path like "Content/<template_path>" in this case remove template
+ $params['pass_template'] = false;
+ }
+
+ $ret .= $regs[1] . '/';
+ }
+
+ $params['category_processed'] = true;
+ }
+
+ // reset category page
+ $force_page_adding = false;
+ if (array_key_exists('reset', $params) && $params['reset']) {
+ unset($params['reset']);
+
+ if ($processed_params['m_cat_id']) {
+ $processed_params['m_cat_page'] = 1;
+ $force_page_adding = true;
+ }
+ }
+
+ if ((array_key_exists('category_processed', $params) && $params['category_processed'] && ($processed_params['m_cat_page'] > 1)) || $force_page_adding) {
+ // category name was added before AND category page number found
+ $ret = rtrim($ret, '/') . '_' . $processed_params['m_cat_page'] . '/';
+ }
+
+ $template = array_key_exists('t', $params) ? $params['t'] : false;
+ $category_template = $processed_params['m_cat_id'] ? $this->Application->getCache('category_designs', $processed_params['m_cat_id']) : '';
+
+ if ((strtolower($template) == '__default__') && ($processed_params['m_cat_id'] == 0)) {
+ // for "Home" category set template to index when not set
+ $template = 'index';
+ }
+
+ // remove template from url if it is category index cached template
+ if (($template == $category_template) || (mb_strtolower($template) == '__default__')) {
+ // given template is also default template for this category or '__default__' given
+ $params['pass_template'] = false;
+ }
+
+ if ($template && $params['pass_template']) {
+ $ret .= $template . '/';
+ }
+
+ return mb_strtolower( rtrim($ret, '/') );
+ }
+
+ /**
+ * Gets language part from url
+ *
+ * @param Array $url_parts
+ * @param Array $vars
+ * @return bool
+ */
+ function _parseLanguage(&$url_parts, &$vars)
+ {
+ if (!$url_parts) {
+ return 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;
+ return true;
+ }
+
+ array_unshift($url_parts, $url_part);
+
+ return false;
+ }
+
+ /**
+ * Gets theme part from url
+ *
+ * @param Array $url_parts
+ * @param Array $vars
+ * @return bool
+ */
+ function _parseTheme(&$url_parts, &$vars)
+ {
+ if (!$url_parts) {
+ return 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;
+ return true;
+ }
+
+ array_unshift($url_parts, $url_part);
+
+ return false;
+ }
+
+ /**
+ * Checks if whole url_parts matches a whole In-CMS page
+ *
+ * @param array $url_parts
+ * @return boolean
+ */
+ function _parseFriendlyUrl($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;
+ }
+
+ /**
+ * Set's 1st page for all modules (will be used when not passed in url)
+ *
+ * @param Array $vars
+ */
+ function _setDefaultPages(&$vars)
+ {
+ // set 1st page for all rewrite listeners, since we don't know which of them will need it
+ foreach ($this->Application->RewriteListeners as $prefix => $listener) {
+ $vars[$prefix . '_Page'] = 1;
+ }
+ }
+
+ /**
+ * Set's page (when found) to all modules
+ *
+ * @param Array $url_parts
+ * @param Array $vars
+ * @return string
+ */
+ function _parsePage(&$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->RewriteListeners as $prefix => $listener) {
+ $vars[$prefix . '_id'] = 0;
+ $vars[$prefix . '_Page'] = $page_number;
+ }
+
+ array_pop($url_parts);
+
+ return true;
+ }
+
+ /**
+ * Extracts category part from url
+ *
+ * @param Array $url_parts
+ * @param Array $vars
+ * @return bool
+ */
+ function _parseCategory($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;
+ }
+
+ return $res;
+ }
+
+ /**
+ * Builds/parses category item part of url
+ *
+ * @param int $rewrite_mode Mode in what rewrite listener was called. Possbile two modes: REWRITE_MODE_BUILD, REWRITE_MODE_PARSE.
+ * @param string $prefix Prefix, that listener uses for system integration
+ * @param Array $params Params, that are used for url building or created during url parsing.
+ * @param Array $url_parts Url parts to parse (only for parsing).
+ * @param bool $keep_events Keep event names in resulting url (only for building).
+ * @return bool Return true to continue to next listener; return false (when building) not to rewrite given prefix; return false (when parsing) to stop processing at this listener.
+ */
+ function CategoryItemRewriteListener($rewrite_mode = REWRITE_MODE_BUILD, $prefix, &$params, &$url_parts, $keep_events = false)
+ {
+ static $parsed = false;
+
+ if ($rewrite_mode == REWRITE_MODE_BUILD) {
+ return $this->_buildCategoryItemUrl($prefix, $params, $keep_events);
+ }
+
+ if (!$parsed) {
+ $this->_modulePrefix = $this->_parseCategoryItemUrl($url_parts, $params);
+ if ($this->_modulePrefix !== false) {
+ $params['pass'][] = $this->_modulePrefix;
+ $this->_partsFound[] = 'parseCategoryItemUrl';
+ }
+
+ $parsed = true;
+ }
+
+ return true;
+ }
+
+ /**
+ * Build category teim part of url
+ *
+ * @param string $prefix_special
+ * @param Array $params
+ * @param bool $keep_events
+ * @return string
+ */
+ function _buildCategoryItemUrl($prefix_special, &$params, $keep_events)
+ {
+ $ret = '';
+ list ($prefix) = explode('.', $prefix_special);
+ $processed_params = $this->getProcessedParams($prefix_special, $params, $keep_events);
+
+ if ($processed_params === false) {
+ return '';
+ }
+
+ if ($processed_params[$prefix_special . '_id']) {
+ // this allows to fill 3 cache records with one query (see this method for details)
+ $category_id = array_key_exists('m_cat_id', $params) ? $params['m_cat_id'] : $this->Application->GetVar('m_cat_id');
+ $category_filename = $this->Application->getFilename('c', $category_id);
+
+ // if template is also item template of category, then remove template
+ $template = array_key_exists('t', $params) ? $params['t'] : false;
+
+ $item_template = $this->GetItemTemplate($category_id, $prefix);
+
+ if ($template == $item_template || strtolower($template) == '__default__') {
+ // given template is also default template for this category item or '__default__' given
+ $params['pass_template'] = false;
+ }
+
+ // get item's filename
+ if ($prefix == 'bb') {
+ $ret .= 'bb_' . $processed_params[$prefix_special . '_id'] . '/';
+ }
+ else {
+ $filename = $this->Application->getFilename($prefix, $processed_params[$prefix_special . '_id'], $category_id);
+ if ($filename !== false) {
+ $ret .= $filename . '/';
+ }
+ }
+ } else {
+ if ($processed_params[$prefix_special . '_Page'] == 1) {
+ // when printing category items and we are on the 1st page -> there is no information about
+ // category item prefix and $params['pass_category'] will not be added automatically
+ $params['pass_category'] = true;
+ }
+ else {
+ $ret .= $processed_params[$prefix_special . '_Page'] . '/';
+ }
+ }
+
+ return mb_strtolower( rtrim($ret, '/') );
+ }
+
+ /**
+ * Sets template and id, corresponding to category item given in url
+ *
+ * @param Array $url_parts
+ * @param Array $vars
+ * @return bool|string
+ */
+ function _parseCategoryItemUrl(&$url_parts, &$vars)
+ {
+ 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, $regs)) {
+ // process topics separatly, because they don't use item filenames
+ array_pop($url_parts);
+
+ return $this->_parseTopicUrl($regs[1], $vars);
+ }
+
+ // 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 ($item_id) {
+ if ($item_template) {
+ // when template is found in category -> set it
+ $vars['t'] = $item_template;
+ }
+
+ // we have category item id
+ $vars[$module_prefix . '_id'] = $item_id;
+
+ return $module_prefix;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Set's template and topic id corresponding to topic given in url
+ *
+ * @param int $topic_id
+ * @param Array $vars
+ * @return string
+ */
+ function _parseTopicUrl($topic_id, &$vars)
+ {
+ $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);
+
+ $item_template = $this->GetItemTemplate($cat_item, 'bb');
+
+ if ($item_template) {
+ $vars['t'] = $item_template;
+ }
+
+ $vars['bb_id'] = $topic_id;
+
+ return 'bb';
+ }
+
+ /**
+ * Returns enviroment variable values for given prefix (uses directly given params, when available)
+ *
+ * @param string $prefix_special
+ * @param Array $params
+ * @param bool $keep_events
+ * @return Array
+ */
+ function getProcessedParams($prefix_special, &$params, $keep_events)
+ {
+ list ($prefix) = explode('.', $prefix_special);
+
+ $query_vars = $this->Application->getUnitOption($prefix, 'QueryString');
+ if (!$query_vars) {
+ // given prefix doesn't use "env" variable to pass it's data
+ return false;
+ }
+
+ $event_key = array_search('event', $query_vars);
+ if ($event_key) {
+ // pass through event of this prefix
+ unset($query_vars[$event_key]);
+ }
+
+ if (array_key_exists($prefix_special . '_event', $params) && !$params[$prefix_special . '_event']) {
+ // if empty event, then remove it from url
+ unset( $params[$prefix_special . '_event'] );
+ }
+
+ // if pass events is off and event is not implicity passed
+ if (!$keep_events && !array_key_exists($prefix_special . '_event', $params)) {
+ unset($params[$prefix_special . '_event']); // remove event from url if requested
+ //otherwise it will use value from get_var
+ }
+
+ $processed_params = Array ();
+ foreach ($query_vars as $index => $var_name) {
+ // if value passed in params use it, otherwise use current from application
+ $var_name = $prefix_special . '_' . $var_name;
+ $processed_params[$var_name] = array_key_exists($var_name, $params) ? $params[$var_name] : $this->Application->GetVar($var_name);
+ if (array_key_exists($var_name, $params)) {
+ unset($params[$var_name]);
+ }
+ }
+
+ return $processed_params;
+ }
+
+ /**
+ * Returns module item details template specified in given category custom field for given module prefix
+ *
+ * @param int|Array $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;
+ }
+
+ /**
+ * Loads all registered rewrite listeners, so they could be quickly accessed later
+ *
+ */
+ function initRewriteListeners()
+ {
+ static $init_done = false;
+
+ if ($init_done) {
+ return ;
+ }
+
+ foreach ($this->Application->RewriteListeners as $prefix => $listener_data) {
+ list ($listener_prefix, $listener_method) = explode(':', $listener_data['listener']);
+ $listener =& $this->Application->recallObject($listener_prefix);
+
+ $this->Application->RewriteListeners[$prefix] = Array (&$listener, $listener_method);
+ }
+
+ $init_done = true;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Sets default parsed values before actual url parsing
+ *
+ * @param Array $vars
+ */
+ 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;
+ }
+ }
+ }
+ }
+?>
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/mod_rewrite_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.11.2.9
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/priority_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/priority_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/priority_helper.php (revision 12306)
@@ -0,0 +1,175 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kPriorityHelper extends kHelper {
+
+
+ /**
+ * Prepares options for priority dropdown
+ *
+ * @param kEvent $event
+ * @param bool $is_new for newly created items add new priority to the end
+ * @param string $constrain constrain for priority selection (if any)
+ *
+ */
+ function preparePriorities(&$event, $is_new = false, $constrain = '')
+ {
+ $object =& $event->getObject();
+
+ $field_options = $object->GetFieldOptions('Priority');
+ $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
+
+ $sql = 'SELECT COUNT(*)
+ FROM '.$table_name;
+ if ($constrain) {
+ $sql .= ' WHERE '.$constrain;
+ }
+
+ if (!isset($object->Fields['OldPriority'])) {
+ $object->VirtualFields['OldPriority'] = Array('type' => 'int', 'default' => 0);
+ }
+
+ $items_count = $this->Conn->GetOne($sql);
+
+ // instanceof is not used, because PHP4 doesn't support it
+ $current_priority = is_a($object, 'kDBList') ? 0 : $object->GetDBField('Priority');
+
+ if ($is_new || $current_priority == -($items_count+1)) {
+ $items_count++;
+ }
+
+ if ($is_new) {
+ // add new item to the end of list
+ $object->SetDBField('Priority', -$items_count);
+ $object->SetDBField('OldPriority', -$items_count);
+ }
+ else {
+ $object->SetDBField('OldPriority', $current_priority);
+ }
+
+ for ($i = 1; $i <= $items_count; $i++) {
+ $field_options['options'][-$i] = $i;
+ }
+
+ $object->SetFieldOptions('Priority', $field_options);
+ // storing prioriry right after load for comparing when updating
+ }
+
+ /**
+ * Updates priorities for changed items
+ *
+ * @param kEvent $event
+ * @param Array $changes = Array (ID => Array ('parent' => ..., 'new' => ..., 'old' => ...), ...)
+ * @param Array $new_ids = Array (temp_id => live_id)
+ * @param string $constrain
+ */
+ function updatePriorities(&$event, $changes, $new_ids, $constrain = '')
+ {
+ if (!$changes) {
+ // no changes to process
+ return Array ();
+ }
+ list ($id, $pair) = each($changes);
+
+ if (!$id && !array_key_exists('parent', $pair)) {
+ // adding new item without constrain -> priority stays the same
+ return Array ($id);
+ }
+
+ $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
+
+ $ids = array();
+ $not_processed = array_keys($changes);
+
+ foreach ($changes as $id => $pair) {
+ array_push($ids, $id);
+ $constrain = isset($pair['parent']) ? 'ParentId = '.$pair['parent'].' AND ' : '';
+
+ if ($pair['old'] == 'new') {
+ // replace 0 with newly created item id (from $new_ids mapping)
+ $not_processed[ array_search($id, $not_processed) ] = $new_ids[$id];
+ $id = $new_ids[$id];
+
+ $sql = 'SELECT MIN(Priority)
+ FROM '.$table_name.'
+ WHERE '.$constrain.' '.$id_field.' NOT IN ('.implode(',', $not_processed).')';
+ $min_priority = (int)$this->Conn->GetOne($sql) - 1;
+
+ if ($pair['new'] < $min_priority) {
+ $pair['new'] = $min_priority;
+ }
+ $pair['old'] = $min_priority;
+ }
+
+ if ($pair['new'] < $pair['old']) {
+ $set = ' SET Priority = Priority + 1';
+ $where =' WHERE '.$constrain.'
+ Priority >= '.$pair['new'].'
+ AND
+ Priority < '.$pair['old'].'
+ AND
+ '.$id_field.' NOT IN ('.implode(',', $not_processed).')';
+ }
+ elseif ($pair['new'] > $pair['old']) {
+ $set = ' SET Priority = Priority - 1';
+ $where =' WHERE '.$constrain.'
+ Priority > '.$pair['old'].'
+ AND
+ Priority <= '.$pair['new'].'
+ AND
+ '.$id_field.' NOT IN ('.implode(',', $not_processed).')';
+ }
+ else {
+ $set = 'SET Priority = '.$pair['new'];
+ $where = ' WHERE '.$id_field.' = '.$id;
+ }
+ $ids = array_merge($ids, $this->Conn->GetCol('SELECT '.$id_field.' FROM '.$table_name.$where));
+ $q = 'UPDATE '.$table_name.' '.$set.$where;
+ $this->Conn->Query($q);
+
+ unset( $not_processed[array_search($id, $not_processed)] );
+ }
+ return $ids;
+ }
+
+ /**
+ * Recalculates priorities
+ *
+ * @param kEvent $event
+ * @param string $constrain
+ */
+ function recalculatePriorities(&$event, $constrain = '')
+ {
+ $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
+
+ $sql = 'SELECT '.$id_field.'
+ FROM '.$table_name.
+ ($constrain ? ' WHERE '.$constrain : '').'
+ ORDER BY Priority DESC';
+
+ $items = $this->Conn->GetCol($sql);
+
+ foreach ($items as $item_number => $item_id) {
+ $sql = 'UPDATE '.$table_name.'
+ SET Priority = '.-($item_number + 1).'
+ WHERE '.$id_field.' = '.$item_id;
+ $this->Conn->Query($sql);
+ }
+ return $items;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/priority_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.2.2.4
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/image_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/image_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/image_helper.php (revision 12306)
@@ -0,0 +1,594 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class ImageHelper extends kHelper {
+
+ /**
+ * Parses format string into array
+ *
+ * @param string $format sample format: "resize:300x500;wm:inc/wm.png|c|-20"
+ * @return Array sample result: Array('max_width' => 300, 'max_height' => 500, 'wm_filename' => 'inc/wm.png', 'h_margin' => 'c', 'v_margin' => -20)
+ */
+ function parseFormat($format)
+ {
+ $res = Array ();
+
+ $format_parts = explode(';', $format);
+ foreach ($format_parts as $format_part) {
+ if (preg_match('/resize:(\d*)x(\d*)/', $format_part, $regs)) {
+ $res['max_width'] = $regs[1];
+ $res['max_height'] = $regs[2];
+ }
+ elseif (preg_match('/wm:([^\|]*)\|([^\|]*)\|([^\|]*)/', $format_part, $regs)) {
+ $res['wm_filename'] = FULL_PATH.THEMES_PATH.'/'.$regs[1];
+ $res['h_margin'] = strtolower($regs[2]);
+ $res['v_margin'] = strtolower($regs[3]);
+ }
+ elseif (preg_match('/crop:([^\|]*)\|([^\|]*)/', $format_part, $regs)) {
+ $res['crop_x'] = strtolower($regs[1]);
+ $res['crop_y'] = strtolower($regs[2]);
+ }
+ elseif ($format_part == 'img_size' || $format_part == 'img_sizes') {
+ $res['image_size'] = true;
+ }
+ elseif (preg_match('/fill:(.*)/', $format_part, $regs)) {
+ $res['fill'] = $regs[1];
+ }
+ }
+
+ return $res;
+ }
+
+ /**
+ * Resized given image to required dimensions & saves resized image to "resized" subfolder in source image folder
+ *
+ * @param string $src_image full path to image (on server)
+ * @param mixed $max_width maximal allowed resized image width or false if no limit
+ * @param mixed $max_height maximal allowed resized image height or false if no limit
+ * @return string direct url to resized image
+ */
+ function ResizeImage($src_image, $max_width, $max_height = null)
+ {
+ $image_size = false;
+
+ if(isset($max_height)) {
+ $params['max_height'] = $max_height;
+ $params['max_width'] = $max_width;
+ }
+ else {
+ $params = $this->parseFormat($max_width);
+
+ if (array_key_exists('image_size', $params)) {
+ // image_size param shouldn't affect resized file name (crc part)
+ $image_size = $params['image_size'];
+ unset($params['image_size']);
+ }
+ }
+
+ if ($params['max_width'] > 0 || $params['max_height'] > 0) {
+ list ($params['target_width'], $params['target_height'], $needs_resize) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height'], $params);
+
+ if (!is_numeric($params['max_width'])) {
+ $params['max_width'] = $params['target_width'];
+ }
+
+ if (!is_numeric($params['max_height'])) {
+ $params['max_height'] = $params['target_height'];
+ }
+
+ $src_path = dirname($src_image);
+
+ if ($needs_resize || array_key_exists('wm_filename', $params) && $params['wm_filename']) {
+ // resize required OR watermarking required -> change resulting image name !
+ $dst_image = preg_replace('/^'.preg_quote($src_path, '/').'(.*)\.(.*)$/', $src_path . DIRECTORY_SEPARATOR . 'resized\\1_' . crc32(serialize($params)) . '.\\2', $src_image);
+ if (!file_exists($dst_image) || filemtime($src_image) > filemtime($dst_image)) {
+ // resized image not available OR should be recreated due source image change
+ $params['dst_image'] = $dst_image;
+ $image_resized = $this->ScaleImage($src_image, $params);
+ if (!$image_resized) {
+ // resize failed, because of server error
+ $dst_image = $src_image;
+ }
+ }
+
+ // resize/watermarking ok
+ $src_image = $dst_image;
+ }
+ }
+
+ if ($image_size) {
+ // return only image size (resized or not)
+ $image_info = $this->getImageInfo($src_image);
+ return $image_info ? $image_info[3] : '';
+ }
+
+ $base_url = rtrim($this->Application->BaseURL(), '/');
+ return str_replace(DIRECTORY_SEPARATOR, '/', preg_replace('/^'.preg_quote(FULL_PATH, '/').'(.*)/', $base_url.'\\1', $src_image));
+ }
+
+ /**
+ * Proportionally resizes given image to destination dimensions
+ *
+ * @param string $src_image full path to source image (already existing)
+ * @param string $dst_image full path to destination image (will be created)
+ * @param int $dst_width destination image width (in pixels)
+ * @param int $dst_height destination image height (in pixels)
+ */
+ function ScaleImage($src_image, $params)
+ {
+ $image_info = $this->getImageInfo($src_image);
+ if (!$image_info) {
+ return false;
+ }
+
+ /*list ($params['max_width'], $params['max_height'], $resized) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height'], $params);
+ if (!$resized) {
+ // image dimensions are smaller or equals to required dimensions
+ return false;
+ }*/
+
+ if (!$this->Application->ConfigValue('ForceImageMagickResize') && function_exists('imagecreatefromjpeg')) {
+ // try to resize using GD
+ $resize_map = Array (
+ 'image/jpeg' => 'imagecreatefromjpeg:imagejpeg:jpg',
+ 'image/gif' => 'imagecreatefromgif:imagegif:gif',
+ 'image/png' => 'imagecreatefrompng:imagepng:png',
+ 'image/bmp' => 'imagecreatefrombmp:imagejpeg:bmp',
+ );
+
+ $mime_type = $image_info['mime'];
+ if (!isset($resize_map[$mime_type])) {
+ return false;
+ }
+
+ list ($read_function, $write_function, $file_extension) = explode(':', $resize_map[$mime_type]);
+
+ $src_image_rs = @$read_function($src_image);
+ if ($src_image_rs) {
+ // when source image has large dimensions (over 1MB filesize), then 16M is not enough
+ set_time_limit(0);
+ ini_set('memory_limit', -1);
+
+ $dst_image_rs = imagecreatetruecolor($params['target_width'], $params['target_height']); // resize target size
+
+ if ($file_extension == 'png') {
+ // preserve transparency of PNG images
+ $transparent_color = imagecolorallocate($dst_image_rs, 0, 0, 0);
+ imagecolortransparent($dst_image_rs, $transparent_color);
+ }
+
+ // 1. resize
+ imagecopyresampled($dst_image_rs, $src_image_rs, 0, 0, 0, 0, $params['target_width'], $params['target_height'], $image_info[0], $image_info[1]);
+
+ $watermark_size = 'target';
+
+ if (array_key_exists('crop_x', $params) || array_key_exists('crop_y', $params)) {
+ // 2.1. crop image to given size
+ $dst_image_rs =& $this->_cropImage($dst_image_rs, $params);
+ $watermark_size = 'max';
+ } elseif (array_key_exists('fill', $params)) {
+ // 2.2. fill image margins from resize with given color
+ $dst_image_rs =& $this->_applyFill($dst_image_rs, $params);
+ $watermark_size = 'max';
+ }
+
+ // 3. apply watermark
+ $dst_image_rs =& $this->_applyWatermark($dst_image_rs, $params[$watermark_size . '_width'], $params[$watermark_size . '_height'], $params);
+
+ return @$write_function($dst_image_rs, $params['dst_image'], 100);
+ }
+ }
+ else {
+ // try to resize using ImageMagick
+ // TODO: implement crop and watermarking using imagemagick
+ exec('/usr/bin/convert '.$src_image.' -resize '.$params['target_width'].'x'.$params['target_height'].' '.$params['dst_image'], $shell_output, $exec_status);
+ return $exec_status == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Fills margins (if any) of resized are with given color
+ *
+ * @param resource $src_image_rs resized image resource
+ * @param Array $params crop parameters
+ * @return resource
+ */
+ function &_applyFill(&$src_image_rs, $params)
+ {
+ $x_position = round(($params['max_width'] - $params['target_width']) / 2); // center
+ $y_position = round(($params['max_height'] - $params['target_height']) / 2); // center
+
+ // crop resized image
+ $fill_image_rs = imagecreatetruecolor($params['max_width'], $params['max_height']);
+
+ $fill = $params['fill'];
+
+ if (substr($fill, 0, 1) == '#') {
+ // hexdecimal color
+ $color = imagecolorallocate($fill_image_rs, hexdec( substr($fill, 1, 2) ), hexdec( substr($fill, 3, 2) ), hexdec( substr($fill, 5, 2) ));
+ }
+ else {
+ // for now we don't support color names, but we will in future
+ return $src_image_rs;
+ }
+
+ imagefill($fill_image_rs, 0, 0, $color);
+ imagecopy($fill_image_rs, $src_image_rs, $x_position, $y_position, 0, 0, $params['target_width'], $params['target_height']);
+
+ return $fill_image_rs;
+ }
+
+ /**
+ * Crop given image resource using given params and return resulting image resource
+ *
+ * @param resource $src_image_rs resized image resource
+ * @param Array $params crop parameters
+ * @return resource
+ */
+ function &_cropImage(&$src_image_rs, $params)
+ {
+ if ($params['crop_x'] == 'c') {
+ $x_position = round(($params['max_width'] - $params['target_width']) / 2); // center
+ }
+ elseif ($params['crop_x'] >= 0) {
+ $x_position = $params['crop_x']; // margin from left
+ }
+ else {
+ $x_position = $params['target_width'] - ($params['max_width'] - $params['crop_x']); // margin from right
+ }
+
+ if ($params['crop_y'] == 'c') {
+ $y_position = round(($params['max_height'] - $params['target_height']) / 2); // center
+ }
+ elseif ($params['crop_y'] >= 0) {
+ $y_position = $params['crop_y']; // margin from top
+ }
+ else {
+ $y_position = $params['target_height'] - ($params['max_height'] - $params['crop_y']); // margin from bottom
+ }
+
+ // crop resized image
+ $crop_image_rs = imagecreatetruecolor($params['max_width'], $params['max_height']);
+ $crop_image_rs =& $this->_applyFill($crop_image_rs, $params);
+
+ imagecopy($crop_image_rs, $src_image_rs, $x_position, $y_position, 0, 0, $params['target_width'], $params['target_height']);
+
+ return $crop_image_rs;
+ }
+
+ /**
+ * Apply watermark (transparent PNG image) to given resized image resource
+ *
+ * @param resource $src_image_rs
+ * @param int $max_width
+ * @param int $max_height
+ * @param Array $params
+ * @return resource
+ */
+ function &_applyWatermark(&$src_image_rs, $max_width, $max_height, $params)
+ {
+ $watermark_file = array_key_exists('wm_filename', $params) ? $params['wm_filename'] : false;
+
+ if (!$watermark_file || !file_exists($watermark_file)) {
+ // no watermark required, or provided watermark image is missing
+ return $src_image_rs;
+ }
+
+ $watermark_img_rs = imagecreatefrompng($watermark_file);
+ list ($watermark_width, $watermark_height) = $this->getImageInfo($watermark_file);
+
+ imagealphablending($src_image_rs, true);
+
+ if ($params['h_margin'] == 'c') {
+ $x_position = round($max_width / 2 - $watermark_width / 2); // center
+ }
+ elseif ($params['h_margin'] >= 0) {
+ $x_position = $params['h_margin']; // margin from left
+ }
+ else {
+ $x_position = $max_width - ($watermark_width - $params['h_margin']); // margin from right
+ }
+
+ if ($params['v_margin'] == 'c') {
+ $y_position = round($max_height / 2 - $watermark_height / 2); // center
+ }
+ elseif ($params['v_margin'] >= 0) {
+ $y_position = $params['v_margin']; // margin from top
+ }
+ else {
+ $y_position = $max_height - ($watermark_height - $params['v_margin']); // margin from bottom
+ }
+
+ imagecopy($src_image_rs, $watermark_img_rs, $x_position, $y_position, 0, 0, $watermark_width, $watermark_height);
+
+ return $src_image_rs;
+ }
+
+ /**
+ * Returns destination image size without actual resizing (useful for <img .../> HTML tag)
+ *
+ * @param string $src_image full path to source image (already existing)
+ * @param int $dst_width destination image width (in pixels)
+ * @param int $dst_height destination image height (in pixels)
+ * @param Array $params
+ * @return Array resized image dimensions (0 - width, 1 - height)
+ */
+ function GetImageDimensions($src_image, $dst_width, $dst_height, $params)
+ {
+ $image_info = $this->getImageInfo($src_image);
+ if (!$image_info) {
+ return false;
+ }
+
+ $orig_width = $image_info[0];
+ $orig_height = $image_info[1];
+
+ $too_large = is_numeric($dst_width) ? ($orig_width > $dst_width) : false;
+ $too_large = $too_large || (is_numeric($dst_height) ? ($orig_height > $dst_height) : false);
+
+ if ($too_large) {
+ $width_ratio = $dst_width ? $dst_width / $orig_width : 1;
+ $height_ratio = $dst_height ? $dst_height / $orig_height : 1;
+
+ if (array_key_exists('crop_x', $params) || array_key_exists('crop_y', $params)) {
+ // resize by smallest inverted radio
+ $resize_by = $this->_getCropImageMinRatio($image_info, $dst_width, $dst_height);
+ $ratio = $resize_by == 'width' ? $width_ratio : $height_ratio;
+ }
+ else {
+ $ratio = min($width_ratio, $height_ratio);
+ }
+
+ $width = ceil($orig_width * $ratio);
+ $height = ceil($orig_height * $ratio);
+ }
+ else {
+ $width = $orig_width;
+ $height = $orig_height;
+ }
+
+ return Array ($width, $height, $too_large);
+ }
+
+ /**
+ * Returns ratio type with smaller relation of original size to target size
+ *
+ * @param Array $image_info image information from "ImageHelper::getImageInfo"
+ * @param int $dst_width destination image width (in pixels)
+ * @param int $dst_height destination image height (in pixels)
+ * @return Array
+ */
+ function _getCropImageMinRatio($image_info, $dst_width, $dst_height)
+ {
+ $width_ratio = $dst_width ? $image_info[0] / $dst_width : 1;
+ $height_ratio = $dst_height ? $image_info[1] / $dst_height : 1;
+
+ return $width_ratio < $height_ratio ? 'width' : 'height';
+ }
+
+ /**
+ * Returns image dimensions + checks if given file is existing image
+ *
+ * @param string $src_image full path to source image (already existing)
+ * @return mixed
+ */
+ function getImageInfo($src_image)
+ {
+ if (!file_exists($src_image)) {
+ return false;
+ }
+
+ $image_info = @getimagesize($src_image);
+ if (!$image_info) {
+ trigger_error('Image <b>'.$src_image.'</b> <span class="debug_error">missing or invalid</span>', E_USER_WARNING);
+ return false;
+ }
+
+ return $image_info;
+ }
+
+ /**
+ * Returns maximal image size (width & height) among fields specified
+ *
+ * @param kDBItem $object
+ * @param string $fields
+ * @param string $format any format, that returns full url (e.g. files_resized:WxH, resize:WxH, full_url, full_urls)
+ * @return string
+ */
+ function MaxImageSize(&$object, $fields, $format = null)
+ {
+ static $cached_sizes = Array ();
+
+ $cache_key = $object->getPrefixSpecial().'_'.$object->GetID();
+ if (!isset($cached_sizes[$cache_key])) {
+ $images = Array ();
+
+ $fields = explode(',', $fields);
+ foreach ($fields as $field) {
+ $image_data = $object->GetField($field, $format);
+ if (!$image_data) {
+ continue;
+ }
+
+ $images = array_merge($images, explode('|', $image_data));
+ }
+
+ $max_width = 0;
+ $max_height = 0;
+ $base_url = rtrim($this->Application->BaseURL(), '/');
+
+ foreach ($images as $image_url) {
+ $image_path = preg_replace('/^'.preg_quote($base_url, '/').'(.*)/', FULL_PATH.'\\1', $image_url);
+ $image_info = $this->getImageInfo($image_path);
+ $max_width = max($max_width, $image_info[0]);
+ $max_height = max($max_height, $image_info[1]);
+ }
+
+ $cached_sizes[$cache_key] = Array ($max_width, $max_height);
+ }
+
+ return $cached_sizes[$cache_key];
+ }
+
+ /**
+ * Puts existing item images (from subitem) to virtual fields (in main item)
+ *
+ * @param kCatDBItem $object
+ */
+ function LoadItemImages(&$object)
+ {
+ if (!$this->Application->prefixRegistred($object->Prefix.'-img')) {
+ return ;
+ }
+
+ $max_image_count = $this->Application->ConfigValue($object->Prefix.'_MaxImageCount');
+
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'Images
+ WHERE ResourceId = '.$object->GetDBField('ResourceId').'
+ ORDER BY Priority DESC
+ LIMIT 0, ' . (int)$max_image_count;
+ $item_images = $this->Conn->Query($sql);
+
+ $image_counter = 1;
+ foreach ($item_images as $item_image) {
+ $image_path = $item_image['ThumbPath'];
+ if ($item_image['DefaultImg'] == 1 || $item_image['Name'] == 'main') {
+ // process primary image separately
+ if (array_key_exists('PrimaryImage', $object->Fields)) {
+ $object->SetDBField('PrimaryImage', $image_path);
+ $object->SetOriginalField('PrimaryImage', $image_path);
+ $object->Fields['PrimaryImage']['original_field'] = $item_image['Name'];
+
+ $this->_loadCustomFields($object, $item_image, 0);
+ }
+ continue;
+ }
+
+ if (abs($item_image['Priority'])) {
+ // use Priority as image counter, when specified
+ $image_counter = abs($item_image['Priority']);
+ }
+
+ if (array_key_exists('Image'.$image_counter, $object->Fields)) {
+ $object->SetDBField('Image'.$image_counter, $image_path);
+ $object->SetOriginalField('Image'.$image_counter, $image_path);
+ $object->Fields['Image'.$image_counter]['original_field'] = $item_image['Name'];
+
+ $this->_loadCustomFields($object, $item_image, $image_counter);
+ }
+ $image_counter++;
+ }
+ }
+
+ /**
+ * Saves newly uploaded images to external image table
+ *
+ * @param kCatDBItem $object
+ */
+ function SaveItemImages(&$object)
+ {
+ if (!$this->Application->prefixRegistred($object->Prefix.'-img')) {
+ return ;
+ }
+
+ $table_name = $this->Application->getUnitOption('img', 'TableName');
+ $max_image_count = $this->Application->getUnitOption($object->Prefix, 'ImageCount'); // $this->Application->ConfigValue($object->Prefix.'_MaxImageCount');
+
+ $i = 0;
+ while ($i < $max_image_count) {
+ $field = $i ? 'Image'.$i : 'PrimaryImage';
+ $field_options = $object->GetFieldOptions($field);
+
+ $image_src = $object->GetDBField($field);
+ if ($image_src) {
+ if (isset($field_options['original_field'])) {
+ $key_clause = 'Name = '.$this->Conn->qstr($field_options['original_field']).' AND ResourceId = '.$object->GetDBField('ResourceId');
+
+ if ($object->GetDBField('Delete'.$field)) {
+ // if item was cloned, then new filename is in db (not in $image_src)
+ $sql = 'SELECT ThumbPath
+ FROM '.$table_name.'
+ WHERE '.$key_clause;
+ $image_src = $this->Conn->GetOne($sql);
+ if (@unlink(FULL_PATH.$image_src)) {
+ $sql = 'DELETE FROM '.$table_name.'
+ WHERE '.$key_clause;
+ $this->Conn->Query($sql);
+ }
+ }
+ else {
+ // image record found -> update
+ $fields_hash = Array (
+ 'ThumbPath' => $image_src,
+ );
+ $this->_saveCustomFields($object, $fields_hash, $i);
+
+ $this->Conn->doUpdate($fields_hash, $table_name, $key_clause);
+ }
+ }
+ else {
+ // image record not found -> create
+ $fields_hash = Array (
+ 'ResourceId' => $object->GetDBField('ResourceId'),
+ 'Name' => $field,
+ 'AltName' => $field,
+ 'Enabled' => STATUS_ACTIVE,
+ 'DefaultImg' => $i ? 0 : 1, // first image is primary, others not primary
+ 'ThumbPath' => $image_src,
+ 'Priority' => ($i == 0)? 0 : $i * (-1),
+ );
+ $this->_saveCustomFields($object, $fields_hash, $i);
+
+ $this->Conn->doInsert($fields_hash, $table_name);
+ $field_options['original_field'] = $field;
+ $object->SetFieldOptions($field, $field_options);
+ }
+ }
+ $i++;
+ }
+ }
+
+ /**
+ * Adds ability to load custom fields along with main image field
+ *
+ * @param kCatDBItem $object
+ * @param Array $fields_hash
+ * @param int $counter 0 - primary image, other number - additional image number
+ */
+ function _loadCustomFields(&$object, $fields_hash, $counter)
+ {
+ $field_name = $counter ? 'Image' . $counter . 'Alt' : 'PrimaryImageAlt';
+
+ $object->SetDBField($field_name, (string)$fields_hash['AltName']);
+ }
+
+ /**
+ * Adds ability to save custom field along with main image save
+ *
+ * @param kCatDBItem $object
+ * @param Array $fields_hash
+ * @param int $counter 0 - primary image, other number - additional image number
+ */
+ function _saveCustomFields(&$object, &$fields_hash, $counter)
+ {
+ $field_name = $counter ? 'Image' . $counter . 'Alt' : 'PrimaryImageAlt';
+
+ $fields_hash['AltName'] = (string)$object->GetDBField($field_name);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/image_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.6.2.14
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/rating_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/rating_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/rating_helper.php (revision 12306)
@@ -0,0 +1,195 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class RatingHelper extends kHelper {
+
+ /**
+ * One star width/height in pixels
+ *
+ * @var int
+ */
+ var $ratingUnitWidth = 25;
+ var $ratingSmallUnitWidth = 20;
+
+ /**
+ * Maximal star count
+ *
+ * @var int
+ */
+ var $ratingMaximal = 5;
+
+ var $_phrases = Array (
+ 'current_rating' => 'lu_CurrentRating',
+ 'vote_title' => 'lu_VoteTitle',
+ 'vote_count' => 'lu_VoteCount',
+ 'invalid_rating' => 'lu_InvalidRating',
+ 'already_voted' => 'lu_AlreadyVoted',
+ 'thanks_for_voting' => 'lu_ThanksForVoting',
+ );
+
+ /**
+ * Draws rating bar for a given category item
+ *
+ * @param kDBItem $object
+ * @param bool $show_div
+ * @param string $additional_msg
+ * @return string
+ */
+ function ratingBar(&$object, $show_div = true, $additional_msg = '', $additional_style = '')
+ {
+ $perm_prefix = $this->Application->getUnitOption($object->Prefix, 'PermItemPrefix');
+ $static = !$this->Application->CheckPermission($perm_prefix . '.RATE', 0, $object->GetDBField('CategoryId'));
+
+ $total_votes = $object->GetDBField('CachedVotesQty');
+ $total_rating = $object->GetDBField('CachedRating') * $total_votes;
+
+ $spam_helper =& $this->Application->recallObject('SpamHelper');
+ /* @var $spam_helper SpamHelper */
+
+ $config_mapping = $this->Application->getUnitOption($object->Prefix, 'ConfigMapping');
+ $review_settings = $config_mapping['RatingDelayValue'].':'.$config_mapping['RatingDelayInterval'];
+ $spam_helper->InitHelper($object->GetDBField('ResourceId'), 'Rating', $review_settings);
+
+ $user_voted = $spam_helper->InSpamControl();
+
+ // now draw the rating bar
+ $unit_selected_width = $additional_style? $this->ratingSmallUnitWidth : $this->ratingUnitWidth;
+ $rating_width = $total_votes ? @number_format($total_rating / $total_votes, 2) * $unit_selected_width : 0;
+ $rating1 = $total_votes ? @number_format($total_rating / $total_votes, 1) : 0;
+ $rating2 = $total_votes ? @number_format($total_rating / $total_votes, 2) : 0;
+
+ $rater = '<span class="inline-rating">
+ <ul class="star-rating '.$additional_style.'" style="width: ' . $unit_selected_width * $this->ratingMaximal . 'px;">
+ <li class="current-rating" style="width: ' . $rating_width . 'px;">' . $this->_replaceInPhrase('current_rating', Array ('<strong>' . $rating2 . '</strong>', $this->ratingMaximal)) . '</li>'."\n";;
+
+ if (!$static && !$user_voted) {
+ // allow to set rating when not static and user not voted before
+ for ($ncount = 1; $ncount <= $this->ratingMaximal; $ncount++) {
+ $rater .= '<li><a href="#vote-' . $ncount . '" onclick="aRatingManager.makeVote(' . $ncount . ', \'' . $object->Prefix . '\', ' . $object->GetID() . ', \''.$additional_style.'\'); return false;" title="' . $this->_replaceInPhrase('vote_title', Array ($ncount, $this->ratingMaximal)) . '" class="r' . $ncount . '-unit rater" rel="nofollow">' . $ncount . '</a></li>'."\n";
+ }
+ }
+
+ $msg_class = Array ();
+
+ if ($static) {
+ $msg_class[] = 'static';
+ }
+
+ if ($user_voted) {
+ $msg_class[] = 'voted';
+ }
+
+ $rater .= ' </ul></span>';
+
+ // this part is disabled for now, will be addressed once properly review
+// $rater .= ' <p class="' . implode(' ', $msg_class) . '">' .
+ $this->_replaceInPhrase('vote_title', Array('<strong>'.$rating1.'</strong>', $this->ratingMaximal)) . ' ('. $this->_replaceInPhrase('vote_count', Array($total_votes)) . ') </p>';
+
+ $rater .= '&nbsp;<span class="' . implode(' ', $msg_class) . '">'.$additional_msg.'</span>';
+
+ if ($show_div) {
+ // adds div around rating stars (when drawing rating first time)
+ $rater = '<div class="inline-rating" id="page_rating_' . $object->GetID() . '">' . $rater . '</div>';
+ }
+
+ return $rater;
+ }
+
+ /**
+ * Saves user's vote, when allowed
+ *
+ * @param kDBItem $object
+ * @return string
+ */
+ function makeVote(&$object)
+ {
+ $spam_helper =& $this->Application->recallObject('SpamHelper');
+ /* @var $spam_helper SpamHelper */
+
+ $config_mapping = $this->Application->getUnitOption($object->Prefix, 'ConfigMapping');
+ $review_settings = $config_mapping['RatingDelayValue'].':'.$config_mapping['RatingDelayInterval'];
+ $spam_helper->InitHelper($object->GetDBField('ResourceId'), 'Rating', $review_settings);
+
+ if (!$object->isLoaded() || $spam_helper->InSpamControl()) {
+ return '@err:' . $this->_replaceInPhrase('already_voted');
+ }
+
+ $perm_prefix = $this->Application->getUnitOption($object->Prefix, 'PermItemPrefix');
+ $can_rate = $this->Application->CheckPermission($perm_prefix . '.RATE', 0, $object->GetDBField('CategoryId'));
+ $rating = (int)$this->Application->GetVar('rating'); // not numeric rating is from GoogleBot :(
+ $additional_style = $this->Application->GetVar('size');
+
+ if (($rating <= 0) || ($rating > $this->ratingMaximal) || !$can_rate) {
+ return '@err:' . $this->_replaceInPhrase('invalid_rating');
+ }
+
+ // save current rating
+ $fields_hash = Array (
+ 'ItemId' => $object->GetID(),
+ 'RatingValue' => $rating,
+ 'IPAddress' => $_SERVER['REMOTE_ADDR'],
+ 'CreatedOn' => adodb_mktime(),
+ );
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'ItemRating');
+
+ // recalculate average rating
+ $votes_count = $object->GetDBField('CachedVotesQty');
+ $avg_rating = $object->GetDBField('CachedRating');
+
+ $avg_rating = round((($votes_count * $avg_rating) + $rating) / ($votes_count + 1), 2);
+ $object->SetDBField('CachedRating', "$avg_rating");
+ $object->Update();
+
+ $sql = 'UPDATE '.$object->TableName.'
+ SET CachedVotesQty = CachedVotesQty + 1
+ WHERE '.$object->IDField.' = '.$object->GetID();
+ $this->Conn->Query($sql);
+
+ $object->SetDBField('CachedVotesQty', $object->GetDBField('CachedVotesQty') + 1); // for using in template
+
+ // prevent user from voting too quickly
+ $spam_helper->AddToSpamControl();
+
+ return $this->ratingBar($object, false, '<span class="thanks">' . $this->_replaceInPhrase('thanks_for_voting') . '</span>', $additional_style);
+ }
+
+ /*function purgeVotes()
+ {
+ $expired = adodb_mktime() - 86400 * $this->Application->ConfigValue('Timeout_Rating'); // 3600
+
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'ItemRating
+ WHERE CreatedOn < ' . $expired;
+ $this->Conn->Query($sql);
+ }*/
+
+ /**
+ * Performs sprintf on phrase translation using given variables
+ *
+ * @param string $phrase
+ * @param Array $arguments
+ * @return string
+ */
+ function _replaceInPhrase($phrase, $arguments = Array ())
+ {
+ $value = $this->Application->Phrase($this->_phrases[$phrase]);
+
+ if ($arguments) {
+ return vsprintf($value, $arguments);
+ }
+
+ return $value;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/rating_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.2.6
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/country_states_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/country_states_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/country_states_helper.php (revision 12306)
@@ -0,0 +1,121 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kCountryStatesHelper extends kHelper
+ {
+ var $CountriesWithStates = Array('USA', 'CAN');
+
+ function CountryHasStates($country_code)
+ {
+ return !$country_code ? false : in_array($country_code,$this->CountriesWithStates);
+ }
+
+ /**
+ * Prepares states dropdown based on country selected
+ *
+ * @param kEvent $event
+ * @param string $state_field
+ * @param string $country_field
+ */
+ function PopulateStates(&$event, $state_field, $country_field)
+ {
+ static $country_states = Array ();
+
+ $object =& $event->getObject();
+ $country_abbr = $object->GetDBField($country_field);
+
+ if (!$country_abbr) {
+ return ;
+ }
+
+ if (!array_key_exists($country_abbr, $country_states)) {
+ $sql = 'SELECT DestId
+ FROM '.TABLE_PREFIX.'StdDestinations
+ WHERE DestType = 1 AND DestAbbr = '.$this->Conn->qstr($country_abbr);
+ $country_id = $this->Conn->GetOne($sql);
+ if (!$country_id) {
+ return ;
+ }
+
+ $sql = 'SELECT p.Translation as DestName, sd.DestAbbr
+ FROM ' . TABLE_PREFIX . 'StdDestinations AS sd
+ LEFT JOIN ' . TABLE_PREFIX . 'Phrase AS p ON p.Phrase = sd.DestName
+ WHERE DestType = 2 AND DestParentId = ' . $country_id . ' AND LanguageId = ' . $this->Application->GetVar('m_lang') . '
+ ORDER BY Translation';
+
+ $country_states[$country_abbr] = $this->Conn->GetCol($sql, 'DestAbbr');
+ }
+
+ $object->Fields[$state_field]['options'] = $country_states[$country_abbr];
+ $object->Fields[$state_field]['options'][''] = '';
+ }
+
+ /**
+ * Returns valid state code for state name and country code passed
+ *
+ * @param string $state_name
+ * @param string $country_code
+ * @return string
+ */
+ function CheckState($state_name, $country_code)
+ {
+ if( !$this->CountryHasStates($country_code) ) return $state_name;
+
+ $sql = 'SELECT sdStates.DestAbbr
+ FROM '.TABLE_PREFIX.'StdDestinations AS sdStates
+ LEFT JOIN '.TABLE_PREFIX.'Phrase AS p ON p.Phrase = sdStates.DestName
+ LEFT JOIN '.TABLE_PREFIX.'StdDestinations AS sdCountries ON sdStates.DestParentId = sdCountries.DestId
+ WHERE (sdStates.DestType = 2) AND
+ (sdStates.DestParentId = sdCountries.DestId) AND
+ (p.LanguageId = %1$s) AND
+ (sdCountries.DestAbbr = %2$s) AND
+ (
+ (LOWER(sdStates.DestAbbr) = %3$s) OR (LOWER(sdStates.DestAbbr2) = %3$s) OR (LOWER(sdStates.DestName) = %3$s) OR (LOWER(p.Translation) = %3$s)
+ )';
+
+ $state_name = trim( mb_strtolower($state_name) );
+ $sql = sprintf($sql, $this->Application->GetVar('m_lang'), $this->Conn->qstr($country_code), $this->Conn->qstr($state_name) );
+
+ return $this->Conn->GetOne($sql);
+ }
+
+ function CheckStateField(&$event, $state_field, $country_field)
+ {
+
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if($items_info)
+ {
+ list($id, $field_values) = each($items_info);
+ if( isset($field_values[$state_field]) && isset($field_values[$country_field]) )
+ {
+ $user_state = getArrayValue($field_values,$state_field);
+ $valid_state = $this->CheckState($user_state, getArrayValue($field_values,$country_field) );
+ if($valid_state !== false)
+ {
+ $field_values[$state_field] = $valid_state;
+ $items_info[$id] = $field_values;
+ $this->Application->SetVar( $event->getPrefixSpecial(true), $items_info);
+ }
+ else
+ {
+ $object =& $event->getObject();
+ $object->Fields[$state_field]['options'][$user_state] = $user_state;
+ $object->SetError($state_field, 'invalid_state', 'la_invalid_state');
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/country_states_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.4.48.2
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/count_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/count_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/count_helper.php (revision 12306)
@@ -0,0 +1,259 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kCountHelper extends kHelper {
+
+ function kCountHelper()
+ {
+ parent::kHelper();
+
+ // reset expired counts
+ $sql = 'UPDATE '.TABLE_PREFIX.'Counters
+ SET CountValue = NULL
+ WHERE (LifeTime > 0) AND (LastCounted < '.adodb_mktime().' - LifeTime)';
+ $this->Conn->Query($sql);
+ }
+
+ /**
+ * Returns counter value
+ *
+ * @param string $name counter name
+ * @param Array $params counter parameters
+ * @param string $query_name specify query name directly (don't generate from parmeters)
+ * @param bool $multiple_results
+ * @return mixed
+ */
+ function getCounter($name, $params = Array (), $query_name = null, $multiple_results = false)
+ {
+ $clone_counter = false;
+ $query_name = isset($query_name) ? $query_name : rtrim($name.'-'.implode('-', array_values($params)), '-');
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'Counters
+ WHERE Name = '.$this->Conn->qstr($query_name);
+ $count_data = $this->Conn->GetRow($sql);
+
+ if (!$count_data && ($query_name != $name)) {
+ // cloned record not found -> search for origial one
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'Counters
+ WHERE Name = '.$this->Conn->qstr($name);
+ $count_data = $this->Conn->GetRow($sql);
+ $clone_counter = true;
+ }
+
+ if (is_null($count_data['CountValue'])) {
+ $params['PREFIX'] = TABLE_PREFIX;
+ $count_sql = $count_data['CountQuery'];
+
+ foreach ($params as $replace_from => $replace_to) {
+ $count_sql = str_replace('<%'.$replace_from.'%>', $replace_to, $count_sql);
+ }
+
+ if ($multiple_results) {
+ $count_data['CountValue'] = serialize($this->Conn->GetCol($count_sql));
+ }
+ else {
+ $count_data['CountValue'] = $this->Conn->GetOne($count_sql);
+ }
+
+ if ($clone_counter && !$count_data['IsClone']) {
+ // don't clone clones
+ $count_data['CounterId'] = 0;
+ $count_data['Name'] = $query_name;
+ $count_data['IsClone'] = 1;
+ }
+
+ $count_data['LastCounted'] = adodb_mktime();
+ $this->Conn->doInsert($count_data, TABLE_PREFIX.'Counters', 'REPLACE');
+ }
+
+ return $multiple_results ? unserialize($count_data['CountValue']) : $count_data['CountValue'];
+ }
+
+ /**
+ * Resets counter, whitch are affected by one of specified tables
+ *
+ * @param string $tables comma separated tables list used in counting sqls
+ */
+ function resetCounters($tables)
+ {
+ $tables = explode(',', $tables);
+ $prefix_length = strlen(TABLE_PREFIX);
+ foreach ($tables as $index => $table) {
+ // remove prefixes
+ if (substr($table, 0, $prefix_length) == TABLE_PREFIX) {
+ $table = substr($table, $prefix_length);
+ }
+ $tables[$index] = '(TablesAffected LIKE "%|'.$table.'|%")';
+ }
+
+ $sql = 'UPDATE '.TABLE_PREFIX.'Counters
+ SET CountValue = NULL
+ WHERE '.implode(' OR ', $tables);
+
+ $this->Conn->Query($sql);
+ }
+
+ /**
+ * Counts items (of specific type) in category & subcategories
+ *
+ * @param string $prefix
+ * @param Array $params
+ * @param mixed $count_sql
+ * @return int
+ */
+ function CategoryItemCount($prefix, $params, $count_sql = null)
+ {
+ if (!$this->Application->findModule('Var', $prefix)) {
+ // this is not module item
+ return $this->Application->ProcessParsedTag($prefix, 'CategoryItemCount', $params);
+ }
+
+ // 1. get root category for counting
+ $category_id = isset($params['cat_id']) ? $params['cat_id'] : false;
+ if (!is_numeric($category_id)) {
+ $category_id = $this->Application->GetVar('m_cat_id');
+ }
+
+ if (!isset($count_sql)) {
+ $count_sql = 'COUNT(*)';
+ }
+
+ $where_clauses = Array ();
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+
+ // 1. count category items
+ $sql = 'SELECT '.$count_sql.'
+ FROM '.$table_name.' item_table
+ INNER JOIN '.TABLE_PREFIX.'CategoryItems ci ON (ci.ItemResourceId = item_table.ResourceId)
+ INNER JOIN '.TABLE_PREFIX.'Category c ON (ci.CategoryId = c.CategoryId)';
+
+ // 2. count items from subcategories
+ if ($category_id > 0) {
+ // get subcategories of required category
+ $tmp_sql = 'SELECT TreeLeft, TreeRight
+ FROM '.TABLE_PREFIX.'Category
+ WHERE CategoryId = '.$category_id;
+ $tree_info = $this->Conn->GetRow($tmp_sql);
+ $where_clauses[] = 'c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight'];
+ }
+ $where_clauses[] = 'item_table.Status = '.STATUS_ACTIVE;
+
+ if (isset($params['today']) && $params['today']) {
+ $today = adodb_mktime(0,0,0, adodb_date('m'), adodb_date('d'), adodb_date('Y'));
+ $where_clauses[] = 'item_table.CreatedOn >= '.$today;
+ }
+
+ $sql .= ' WHERE ('.implode(') AND (', $where_clauses).')';
+
+ return (int)$this->Conn->GetOne($sql);
+ }
+
+ /**
+ * Counts items (of specific type) from all categories
+ *
+ * @param string $prefix
+ * @param bool $today
+ * @return int
+ */
+ function ItemCount($prefix, $today = false, $count_sql = null)
+ {
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+
+ if (!isset($count_sql)) {
+ $count_sql = 'COUNT(*)';
+ }
+
+ $sql = 'SELECT '.$count_sql.'
+ FROM '.$table_name.' item_table
+ INNER JOIN '.TABLE_PREFIX.'CategoryItems ci ON ci.ItemResourceId = item_table.ResourceId
+ INNER JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
+ INNER JOIN '.TABLE_PREFIX.'PermCache perm_cache ON ci.CategoryId = perm_cache.CategoryId';
+
+ list ($view_perm, $view_filter) = $this->GetPermissionClause($prefix, 'perm_cache');
+ $where_clauses = Array (
+ $view_filter, 'perm_cache.PermId = '.$view_perm, 'ci.PrimaryCat = 1', 'c.Status = '.STATUS_ACTIVE,
+ );
+
+ if ($today) {
+ $today_date = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), adodb_date('Y'));
+ $where_clauses[] = 'item_table.CreatedOn >= '.$today_date;
+ }
+
+ $sql .= ' WHERE ('.implode(') AND (', $where_clauses).')';
+
+ return (int)$this->Conn->GetOne($sql);
+ }
+
+ /**
+ * Returns categories count in system
+ *
+ * @param bool $today
+ * @return int
+ */
+ function CategoryCount($today = false)
+ {
+ $table_name = $this->Application->getUnitOption('c', 'TableName');
+
+ $sql = 'SELECT COUNT(*)
+ FROM '.$table_name.' c
+ INNER JOIN '.TABLE_PREFIX.'PermCache perm_cache ON c.CategoryId = perm_cache.CategoryId';
+
+ list ($view_perm, $view_filter) = $this->GetPermissionClause('c', 'perm_cache');
+ $where_clauses = Array (
+ $view_filter, 'perm_cache.PermId = '.$view_perm, 'c.Status = '.STATUS_ACTIVE,
+ );
+
+ if ($today) {
+ $today_date = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), adodb_date('Y'));
+ $where_clauses[] = 'c.CreatedOn >= '.$today_date;
+ }
+
+ $sql .= ' WHERE ('.implode(') AND (', $where_clauses).')';
+
+ return $this->Conn->GetOne($sql);
+ }
+
+ /**
+ * Returns permission limitation clause for category item lists
+ *
+ * @param string $prefix
+ * @param string $table_alias
+ * @return Array
+ */
+ function GetPermissionClause($prefix, $table_alias)
+ {
+ $view_perm = $this->Application->getCache(__CLASS__ . __FUNCTION__, $prefix);
+ if ($view_perm === false) {
+ $sql = 'SELECT PermissionConfigId
+ FROM '.TABLE_PREFIX.'PermissionConfig
+ WHERE PermissionName = "'.$this->Application->getUnitOption($prefix, 'PermItemPrefix').'.VIEW"';
+ $view_perm = $this->Conn->GetOne($sql);
+
+ $this->Application->setCache(__CLASS__ . __FUNCTION__, $prefix, $view_perm);
+ }
+
+ $groups = explode(',', $this->Application->RecallVar('UserGroups'));
+ foreach ($groups as $group) {
+ $view_filters[] = 'FIND_IN_SET('.$group.', '.$table_alias.'.acl)';
+ }
+
+ $view_filter = implode(' OR ', $view_filters);
+
+ return Array ($view_perm, $view_filter);
+ }
+
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/count_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.4.4.4
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/csv_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/csv_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/csv_helper.php (revision 12306)
@@ -0,0 +1,374 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ safeDefine('EXPORT_STEP', 100); // export by 100 items
+ safeDefine('IMPORT_STEP', 10);
+
+ class kCSVHelper extends kHelper {
+
+ var $PrefixSpecial;
+ var $grid;
+
+ var $delimiter_mapping = Array(0 => "\t", 1 => ',', 2 => ';', 3 => ' ', 4 => ':');
+ var $enclosure_mapping = Array(0 => '"', 1 => "'");
+ var $separator_mapping = Array(0 => "\n", 1 => "\r\n");
+
+ function ExportStep()
+ {
+ $export_data = $this->Application->RecallVar('export_data');
+ $export_rand = $this->Application->RecallVar('export_rand');
+ $get_rand = $this->Application->GetVar('export_rand');
+
+ if($export_data && $export_rand == $get_rand) {
+ $export_data = unserialize($export_data);
+ $first_step = false;
+ }
+ else {
+ // first step
+ $export_data = Array();
+ $export_data['prefix'] = $this->PrefixSpecial;
+ $export_data['grid'] = $this->grid;
+ $export_data['file_name'] = EXPORT_PATH.'/'.$this->ValidateFileName(EXPORT_PATH, 'export_'.$export_data['prefix'].'.csv');
+ $export_data['step'] = EXPORT_STEP;
+ $export_data['delimiter'] = $this->delimiter_mapping[(int)$this->Application->ConfigValue('CSVExportDelimiter')];
+ $export_data['enclosure'] = $this->enclosure_mapping[(int)$this->Application->ConfigValue('CSVExportEnclosure')];
+ $export_data['record_separator'] = $this->separator_mapping[(int)$this->Application->ConfigValue('CSVExportSeparator')];
+ $export_data['page'] = 1;
+
+ $lang_object =& $this->Application->recallObject('lang.current');
+ /* @var $lang_object LanguagesItem */
+ $export_data['source_encoding'] = strtoupper( $lang_object->GetDBField('Charset') );
+ $export_data['encoding'] = $this->Application->ConfigValue('CSVExportEncoding') ? false : 'UTF-16LE';
+
+ $this->Application->StoreVar('export_rand', $get_rand);
+
+ $first_step = true;
+ }
+
+ $file = fopen($export_data['file_name'], $first_step ? 'w' : 'a');
+
+ $prefix_elems = split('\.|_', $export_data['prefix']);
+ $grids = $this->Application->getUnitOption($prefix_elems[0], 'Grids');
+ $grid_config = $grids[ $export_data['grid'] ]['Fields'];
+
+ $list_params = Array('per_page' => $export_data['step'], 'grid' => $export_data['grid']);
+ $list =& $this->Application->recallObject(rtrim(implode('.', $prefix_elems), '.'), $prefix_elems[0].'_List', $list_params);
+ /* @var $list kDBList */
+ $list->SetPage($export_data['page']);
+
+ $list->Query();
+ $list->GoFirst();
+
+ $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
+ /* @var $picker_helper kColumnPickerHelper */
+ $picker_helper->ApplyPicker(rtrim(implode('.', $prefix_elems), '.'), $grid_config, $export_data['grid']);
+
+ if($first_step) {
+ // if UTF-16, write Unicode marker
+ if($export_data['encoding'] == 'UTF-16LE') {
+ fwrite($file, chr(0xFF).chr(0xFE));
+ }
+
+ // inserting header line
+ $headers = Array();
+ foreach($grid_config as $field_name => $field_data) {
+ $header = $this->Application->Phrase( $field_data['title'] );
+ array_push($headers, $header);
+ }
+ $csv_line = getcsvline($headers, $export_data['delimiter'], $export_data['enclosure'], $export_data['record_separator']);
+ if($export_data['encoding']) {
+ $csv_line = mb_convert_encoding($csv_line, $export_data['encoding'], $export_data['source_encoding']);
+ }
+ fwrite($file, $csv_line);
+ }
+
+ while(!$list->EOL())
+ {
+ $data = Array();
+ foreach($grid_config as $field_name => $field_data) {
+ if(isset($field_data['export_field'])) {
+ $field_name = $field_data['export_field'];
+ }
+ $value = $list->GetField($field_name, isset($field_data['format']) ? $field_data['format'] : null);
+ $value = str_replace("\r\n", "\n", $value);
+ $value = str_replace("\r", "\n", $value);
+ array_push($data, $value);
+ }
+ if($export_data['encoding'] == 'UTF-16LE') {
+ fwrite($file, chr(0xFF).chr(0xFE));
+ }
+ $csv_line = getcsvline($data, $export_data['delimiter'], $export_data['enclosure'], $export_data['record_separator']);
+ if($export_data['encoding']) {
+ $csv_line = mb_convert_encoding($csv_line, $export_data['encoding'], $export_data['source_encoding']);
+ }
+ fwrite($file, $csv_line);
+
+ $list->GoNext();
+ }
+
+ $records_processed = $export_data['page'] * $export_data['step'];
+ $percent_complete = min($records_processed / $list->RecordsCount * 100, 100);
+
+ fclose($file);
+
+ if ($records_processed >= $list->RecordsCount) {
+ $this->Application->StoreVar('export_data', serialize($export_data));
+ $this->Application->Redirect($this->Application->GetVar('finish_template'));
+ }
+
+ echo $percent_complete;
+
+ $export_data['page']++;
+ $this->Application->StoreVar('export_data', serialize($export_data));
+ }
+
+ function ValidateFileName($path, $name)
+ {
+ $parts = pathinfo($name);
+ $ext = '.'.$parts['extension'];
+ $filename = mb_substr($parts['basename'], 0, -mb_strlen($ext));
+ $new_name = $filename.$ext;
+ while ( file_exists($path.'/'.$new_name) )
+ {
+ if ( preg_match('/('.preg_quote($filename, '/').'_)([0-9]*)('.preg_quote($ext, '/').')/', $new_name, $regs) ) {
+ $new_name = $regs[1].($regs[2]+1).$regs[3];
+ }
+ else {
+ $new_name = $filename.'_1'.$ext;
+ }
+ }
+ return $new_name;
+ }
+
+ function ExportData($name)
+ {
+ $export_data = unserialize($this->Application->RecallVar('export_data'));
+ return isset($export_data[$name]) ? $export_data[$name] : false;
+ }
+
+ function GetCSV()
+ {
+ safeDefine('DBG_SKIP_REPORTING', 1);
+
+ $export_data = unserialize($this->Application->RecallVar('export_data'));
+ header('Content-type: text/csv');
+ $filename = rtrim(basename($export_data['file_name']), '.csv').'.csv';
+ header('Content-Disposition: attachment; filename="'.$filename.'"');
+ readfile($export_data['file_name']);
+ die();
+ }
+
+ function ImportStart($filename)
+ {
+ if(!file_exists($filename) || !is_file($filename)) return 'cant_open_file';
+
+ $import_data = Array();
+
+ $lang_object =& $this->Application->recallObject('lang.current');
+ /* @var $lang_object LanguagesItem */
+ $import_data['source_encoding'] = strtoupper( $lang_object->GetDBField('Charset') );
+ $import_data['encoding'] = $this->Application->ConfigValue('CSVExportEncoding') ? false : 'UTF-16LE';
+ $import_data['errors'] = '';
+
+ // convert file in case of UTF-16LE
+ if($import_data['source_encoding'] != $import_data['encoding']) {
+ copy($filename, $filename.'.orginal');
+ $file_content = file_get_contents($filename);
+ $file = fopen($filename, 'w');
+ fwrite($file, mb_convert_encoding(str_replace(chr(0xFF).chr(0xFE), '', $file_content), $import_data['source_encoding'], $import_data['encoding']));
+ fclose($file);
+
+ }
+
+ $import_data['prefix'] = $this->PrefixSpecial;
+ $import_data['grid'] = $this->grid;
+ $import_data['file'] = $filename;
+ $import_data['total_lines'] = count(file($filename));
+ if(!$import_data['total_lines']) $import_data['total_lines'] = 1;
+ unset($file_content);
+ $import_data['lines_processed'] = 0;
+ $import_data['delimiter'] = $this->delimiter_mapping[(int)$this->Application->ConfigValue('CSVExportDelimiter')];
+ $import_data['enclosure'] = $this->enclosure_mapping[(int)$this->Application->ConfigValue('CSVExportEnclosure')];
+ $import_data['step'] = IMPORT_STEP;
+ $import_data['not_imported_lines'] = '';
+ $import_data['added'] = 0;
+ $import_data['updated'] = 0;
+
+ $file = fopen($filename, 'r');
+ // getting first line for headers
+ $headers = fgetcsv($file, 8192, $import_data['delimiter'], $import_data['enclosure']);
+ fclose($file);
+
+ $prefix_elems = split('\.|_', $import_data['prefix']);
+ $grids = $this->Application->getUnitOption($prefix_elems[0], 'Grids');
+ $grid_config = $grids[ $import_data['grid'] ]['Fields'];
+
+ $field_list = Array();
+ foreach($grid_config as $field_name => $field_data) {
+ if(isset($field_data['export_field'])) {
+ $field_name = $field_data['export_field'];
+ }
+ $field_label = $this->Application->Phrase( $field_data['title'] );
+ $field_pos = array_search($field_label, $headers);
+ if($field_pos !== false) {
+ $field_list[$field_pos] = $field_name;
+ }
+ }
+
+ if(!count($field_list)) return 'no_matching_columns';
+ $import_data['field_list'] = $field_list;
+
+ // getting key list
+ $field_positions = Array();
+ $config_key_list = $this->Application->getUnitOption($prefix_elems[0], 'ImportKeys');
+ if(!$config_key_list) $config_key_list = Array();
+ array_unshift($config_key_list, Array($this->Application->getUnitOption($prefix_elems[0], 'IDField')));
+
+ $key_list = Array();
+ foreach($config_key_list as $arr_key => $import_key) {
+ $key_list[$arr_key] = is_array($import_key) ? $import_key : Array($import_key);
+
+ foreach($key_list[$arr_key] as $key_field) {
+ $field_positions[$key_field] = array_search($key_field, $import_data['field_list']);
+ if($field_positions[$key_field] === false) {
+ // no such key field combination in imported file
+ unset($key_list[$arr_key]);
+ break;
+ }
+ }
+ }
+ $import_data['key_list'] = $key_list;
+ $import_data['field_positions'] = $field_positions;
+
+ $this->Application->StoreVar('import_data', serialize($import_data));
+ return true;
+ }
+
+ function ImportStep()
+ {
+ $import_data = unserialize($this->Application->RecallVar('import_data'));
+ $prefix_elems = split('\.|_', $import_data['prefix']);
+
+ $object =& $this->Application->recallObject($prefix_elems[0].'.-csvimport', $prefix_elems[0], Array('skip_autoload' => true, 'populate_ml_fields' => true));
+ /* @var $object kDBItem */
+
+ $file = fopen($import_data['file'], 'r');
+ $eof = false;
+ // skipping lines that has been already imported
+ for($i = 0; $i < $import_data['lines_processed'] + 1; $i++) {
+ if(feof($file)) break;
+ fgets($file, 8192);
+ }
+
+ $import_event = new kEvent($prefix_elems[0].'.-csvimport:OnBeforeCSVLineImport');
+
+ for($i = 0; $i < $import_data['step']; $i++) {
+ if(feof($file)) break;
+ $data = fgetcsv($file, 8192, $import_data['delimiter'], $import_data['enclosure']);
+ if(!$data) continue;
+
+ $object->Clear();
+ $action = 'Create';
+
+ // 1. trying to load object by keys
+ foreach($import_data['key_list'] as $key) {
+ $fail = false;
+ $key_array = Array();
+ foreach($key as $key_field) {
+ if(!isset($data[ $import_data['field_positions'][$key_field] ])) {
+ $fail = true;
+ break;
+ }
+ $key_array[$key_field] = $data[ $import_data['field_positions'][$key_field] ];
+ }
+ if($fail) continue;
+ if($object->Load($key_array)) {
+ $action = 'Update';
+ break;
+ }
+ }
+
+ // 2. set object fields
+ foreach($import_data['field_list'] as $position => $field_name) {
+ if(isset($data[$position])) {
+ $object->SetField($field_name, $data[$position]);
+ }
+ }
+
+ // 3. validate item and run event
+ $status = $object->Validate();
+ $import_event->status = $status ? erSUCCESS : erFAIL;
+ $this->Application->HandleEvent($import_event);
+
+ if($import_event->status == erSUCCESS && $object->$action()) {
+ $import_data[ ($action == 'Create') ? 'added' : 'updated' ]++;
+ }
+ else {
+ $msg = '';
+ foreach ($object->FieldErrors as $field => $info) {
+ if (!$info['pseudo']) continue;
+ $msg .= "$field: {$info['pseudo']} ";
+ }
+ $import_data['errors'] .= ($i + $import_data['lines_processed'] + 1).": $msg\n";
+ $import_data['not_imported_lines'] .= ','.($i + $import_data['lines_processed'] + 1);
+ }
+ }
+
+ $import_data['lines_processed'] += $import_data['step'];
+
+ $import_data['not_imported_lines'] = ltrim($import_data['not_imported_lines'], ',');
+ $this->Application->StoreVar('import_data', serialize($import_data));
+
+ $feof = feof($file);
+ fclose($file);
+
+ if($feof) {
+ $this->Application->Redirect($this->Application->GetVar('finish_template'));
+ }
+ else {
+ $percent_complete = floor($import_data['lines_processed'] / $import_data['total_lines'] * 100);
+ if($percent_complete > 99) $percent_complete = 99;
+ echo $percent_complete;
+ }
+ }
+
+ function ImportData($name)
+ {
+ $import_data = unserialize($this->Application->RecallVar('import_data'));
+ return isset($import_data[$name]) ? $import_data[$name] : false;
+ }
+
+ function GetNotImportedLines()
+ {
+ $import_data = unserialize($this->Application->RecallVar('import_data'));
+
+ if(!$import_data['not_imported_lines']) return false;
+ $line_numbers = explode(',', $import_data['not_imported_lines']);
+ $line_numbers[] = 0; // include header row in output
+
+ $file = fopen($import_data['file'], 'r');
+ $eof = false;
+ $result = '';
+ for($i = 0; $i <= max($line_numbers); $i++) {
+ if(feof($file)) break;
+ $line = fgets($file, 8192);
+ if(in_array($i, $line_numbers)) {
+ $result .= $i.':'.$line;
+ }
+ }
+ return $result."\n\n".$import_data['errors'];
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/csv_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.4.4
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/brackets_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/brackets_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/brackets_helper.php (revision 12306)
@@ -0,0 +1,470 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kBracketsHelper extends kHelper {
+
+ /**
+ * Field name holding minimal amount
+ *
+ * @var string
+ */
+ var $min_field = '';
+
+ /**
+ * Field name holding maximal amount
+ *
+ * @var string
+ */
+ var $max_field = '';
+
+ /**
+ * Default values to be set to automtically created price brackets
+ *
+ * @var Array
+ */
+ var $default_values = Array();
+
+ var $defaultStartValue = 1;
+
+ /**
+ * Decimal separator
+ *
+ * @var string
+ */
+ var $_decimalSeparator = '';
+
+ /**
+ * Thousands separator
+ *
+ * @var string
+ */
+ var $_thousandsSeparator = '';
+
+ /**
+ * Current language
+ *
+ * @var LanguagesItem
+ */
+ var $_language = null;
+
+ function kBracketsHelper()
+ {
+ parent::kHelper();
+
+ $this->_language =& $this->Application->recallObject('lang.current');
+ /* @var $lang kDBItem */
+
+ $this->_decimalSeparator = $this->_language->GetDBField('DecimalPoint');
+ $this->_thousandsSeparator = $this->_language->GetDBField('ThousandSep');
+ }
+
+ function InitHelper($min_field, $max_field, $default_values, $default_start_value = null)
+ {
+ $this->min_field = $min_field;
+ $this->max_field = $max_field;
+ $this->default_values = $default_values;
+
+ if (isset($default_start_value)) {
+ $this->defaultStartValue = $default_start_value;
+ }
+ }
+
+ /**
+ * Converts number to operatable form
+ *
+ * @param string $value
+ * @return float
+ */
+ function _parseNumber($value)
+ {
+ $value = str_replace($this->_thousandsSeparator, '', $value);
+ $value = str_replace($this->_decimalSeparator, '.', $value);
+
+ return $value;
+ }
+
+ /**
+ * Returns brackets from form with all numbers parsed
+ *
+ * @param kEvent $event
+ * @return Array
+ */
+ function getBrackets(&$event)
+ {
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+
+ return $this->parseBrackets($items_info);
+ }
+
+ function parseBrackets($brackets)
+ {
+ if (!$brackets) {
+ return $brackets;
+ }
+
+ foreach ($brackets as $id => $field_values) {
+ if (strlen($brackets[$id][$this->min_field])) {
+ $brackets[$id][$this->min_field] = (float)$this->_parseNumber($brackets[$id][$this->min_field]);
+ }
+
+ if (strlen($brackets[$id][$this->max_field])) {
+ $brackets[$id][$this->max_field] = (float)$this->_parseNumber($brackets[$id][$this->max_field]);
+ }
+ }
+
+ return $brackets;
+ }
+
+ /**
+ * Formats given brackets and sets them back to request
+ *
+ * @param kEvent $event
+ * @param Array $brackets
+ */
+ function setBrackets(&$event, $brackets)
+ {
+ $brackets = $this->formatBrackets($brackets);
+
+ $this->Application->SetVar($event->getPrefixSpecial(true), $brackets);
+ }
+
+ function formatBrackets($brackets)
+ {
+ if (!$brackets) {
+ return $brackets;
+ }
+
+ foreach ($brackets as $id => $field_values) {
+ if (strlen($brackets[$id][$this->min_field])) {
+ $brackets[$id][$this->min_field] = $this->_language->formatNumber($brackets[$id][$this->min_field]);
+ }
+
+ if (strlen($brackets[$id][$this->max_field])) {
+ $brackets[$id][$this->max_field] = $this->_language->formatNumber($brackets[$id][$this->max_field]);
+ }
+ }
+
+ return $brackets;
+ }
+
+ /**
+ * Adds 5 more empty brackets to brackets
+ *
+ * @param kEvent $event
+ */
+ function OnMoreBrackets(&$event)
+ {
+ $field_values = $this->getBrackets($event);
+
+ $object =& $event->getObject();
+
+ foreach($field_values as $id => $record)
+ {
+ if($record[$this->max_field] == '&#8734;') $field_values[$id][$this->max_field] = -1;
+ }
+
+ $new_id = (int)$this->Conn->GetOne('SELECT MIN('.$object->IDField.') FROM '.$object->TableName);
+ if($new_id > 0) $new_id = 0;
+ do
+ {
+ $new_id--;
+ }while( $this->arraySearch($field_values, $object->IDField, $new_id) );
+
+
+ $last_max_qty = $this->Conn->GetOne('SELECT MAX('.$this->max_field.') FROM '.$object->TableName);
+ $min_qty = $this->Conn->GetOne('SELECT MIN('.$this->max_field.') FROM '.$object->TableName);
+
+ if($min_qty == -1) $last_max_qty = -1;
+ if(!$last_max_qty) $last_max_qty = $this->defaultStartValue;
+
+
+ for($i = $new_id; $i > $new_id - 5; $i--)
+ {
+ $field_values[$i][$object->IDField] = $i;
+ $field_values[$i][$this->min_field] = ($i == $new_id-4 && $last_max_qty != -1) ? $last_max_qty : '';
+ $field_values[$i][$this->max_field] = ($i == $new_id-4 && $last_max_qty != -1) ? -1 : '';
+ $field_values[$i] = array_merge_recursive2($field_values[$i], $this->default_values);
+ }
+
+ $event->CallSubEvent('OnPreSaveBrackets');
+
+ $this->setBrackets($event, $field_values);
+ }
+
+ /**
+ * Adds infinity bracket
+ *
+ * @param kEvent $event
+ */
+ function OnInfinity(&$event)
+ {
+ $object =& $event->getObject();
+ $infinite_exists = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$object->TableName.' WHERE '.$this->max_field.' = -1');
+ $field_values = $this->getBrackets($event);
+ /*if(is_array($field_values))
+ {
+ foreach($field_values as $values)
+ {
+ $infinite_exists = $infinite_exists || ($values[$this->max_field] == -1);
+ }
+ }*/
+
+ if ($infinite_exists == 0) {
+ reset($field_values);
+ $last_bracket = end($field_values);
+ $new_id = (int)$this->Conn->GetOne('SELECT MIN('.$object->IDField.') FROM '.$object->TableName);
+
+ $brackets_exist = (int)$this->Conn->GetOne('SELECT COUNT(*) FROM '.$object->TableName);
+
+ if($new_id > 0) $new_id = 0;
+ do
+ {
+ $new_id--;
+ }while( $this->arraySearch($field_values, $object->IDField, $new_id) );
+
+ $infinite_bracket[$object->IDField] = $new_id;
+ $infinite_bracket[$this->min_field] = ($brackets_exist > 0) ? $last_bracket[$this->max_field] : $this->defaultStartValue;
+ $infinite_bracket[$this->max_field] = '-1';
+ $infinite_bracket = array_merge_recursive2($infinite_bracket, $this->default_values);
+
+ $field_values[$new_id] = $infinite_bracket;
+ reset($field_values);
+
+ $this->setBrackets($event, $field_values);
+ }
+ }
+
+ /**
+ * Saves brackets to database
+ *
+ * @param kEvent $event
+ */
+ function OnPreSaveBrackets(&$event)
+ {
+ $items_info = $this->getBrackets($event);
+ if ($items_info) {
+ $object =& $event->getObject();
+
+ $linked_info = $object->getLinkedInfo();
+ $stored_ids = $this->Conn->GetCol('SELECT '.$object->IDField.' FROM '.$object->TableName.' WHERE '.$linked_info['ForeignKey'].' = '.$linked_info['ParentId']);
+
+ uasort($items_info, Array(&$this, 'compareBrackets') );
+
+ foreach ($items_info as $item_id => $values) {
+
+ if (in_array($item_id, $stored_ids)) { //if it's already exist
+ $object->SetDefaultValues();
+ $object->Load($item_id);
+ $object->SetFieldsFromHash($values);
+ if (!$object->Validate()) {
+ unset($stored_ids[array_search($item_id, $stored_ids)]);
+ $event->redirect = false;
+ continue;
+ }
+ if( $object->Update($item_id) )
+ {
+ $event->status = erSUCCESS;
+ }
+ else
+ {
+ $event->status = erFAIL;
+ $event->redirect = false;
+ break;
+ }
+ unset( $stored_ids[ array_search($item_id, $stored_ids) ] );
+ }
+ else {
+ $object->SetDefaultValues();
+ $object->SetFieldsFromHash($values);
+ $object->SetDBField($linked_info['ForeignKey'], $linked_info['ParentId']);
+
+ if( $object->Create() )
+ {
+ $object->setTempID();
+ $event->status = erSUCCESS;
+ }
+ }
+ }
+
+ // delete
+ foreach ($stored_ids as $stored_id)
+ {
+ $this->Conn->Query('DELETE FROM '.$object->TableName.' WHERE '.$object->IDField.' = '.$stored_id);
+ }
+
+ }
+ }
+
+ function arrangeBrackets(&$event)
+ {
+ $object =& $event->getObject();
+
+ $temp = $this->getBrackets($event);
+
+ foreach($temp as $id => $record)
+ {
+ if( $record[$this->max_field] == '&#8734;' )
+ {
+ $temp[$id][$this->max_field] = -1;
+ }
+ }
+
+ $temp_orig = $temp;
+ reset($temp);
+ if( is_array($temp) )
+ {
+ // array to store max values (2nd column)
+ $end_values = Array();
+
+ // get minimal value of Min
+ $first_elem = current($temp);
+ $start = $first_elem[$this->min_field];
+ if (!strlen($start)) {
+ $start = $this->defaultStartValue;
+ }
+
+ foreach($temp as $id => $record)
+ {
+ if(
+ // MAX is less than start
+ ($record[$this->max_field] <= $start && $record[$this->max_field] != -1) ||
+ // Max is empty
+ !strlen($record[$this->max_field]) ||
+ // Max already defined in $end_values
+ (array_search($record[$this->max_field], $end_values) !== false)
+ ) { // then delete from brackets list
+ unset($temp[$id]);
+ }
+ else { // this is when ok - add to end_values list
+ $end_values[] = $record[$this->max_field];
+ }
+ }
+
+ // sort brackets by 2nd column (Max values)
+ uasort($temp, Array(&$this, 'compareBrackets') );
+ reset($temp);
+ $first_item = each($temp);
+ $first_item_key = $first_item['key'];
+
+ $linked_info = $object->getLinkedInfo();
+ $sql = 'SELECT %s FROM %s WHERE %s = %s';
+ $ids = $this->Conn->GetCol( sprintf($sql, $object->IDField, $object->TableName, $linked_info['ForeignKey'], $linked_info['ParentId']) );
+ if( is_array($ids) )
+ {
+ usort($ids, Array(&$this, 'sortBracketIDs') );
+ }
+
+// $min_id = min( min($ids) - 1, -1 );
+
+ foreach($temp as $key => $record)
+ {
+ $temp[$key][$this->min_field] = $start;
+ $start = $temp[$key][$this->max_field];
+ }
+ }
+
+ $this->setBrackets($event, $temp);
+
+ return $temp;
+ }
+
+ function compareBrackets($bracket1, $bracket2) // ap_bracket_comp
+ {
+ $bracket1_min = $bracket1[$this->min_field];
+ $bracket1_max = $bracket1[$this->max_field];
+
+ $bracket2_min = $bracket2[$this->min_field];
+ $bracket2_max = $bracket2[$this->max_field];
+
+ // limits
+ if( ($bracket1_min != '') && ($bracket1_max == '') && ($bracket2_min != '') && ($bracket2_max != '') ) return 1;
+ if( ($bracket1_min != '') && ($bracket1_max == '') && ($bracket2_min == '') && ($bracket2_max == '') ) return -1;
+ if( ($bracket1_max == '') && ($bracket2_max != '') ) return 1;
+ if( ($bracket1_max != '') && ($bracket2_max == '') ) return -1;
+
+
+ if( ( ($bracket1_max > $bracket2_max) && ($bracket2_max != -1) ) || ( ($bracket1_max == -1) && ($bracket2_max != -1) ) )
+ {
+ return 1;
+ }
+ elseif( ($bracket1_max < $bracket2_max) || ( ($bracket2_max == -1) && ($bracket1_max != -1) ) )
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ function sortBracketIDs($first_id, $second_id) // pr_bracket_id_sort
+ {
+ $first_abs = abs($first_id);
+ $second_abs = abs($second_id);
+
+ $first_sign = ($first_id == 0) ? 0 : $first_id / $first_abs;
+ $second_sign = ($second_id == 0) ? 0 : $second_id / $second_abs;
+
+ if($first_sign != $second_sign)
+ {
+ if($first_id > $second_id)
+ {
+ $bigger =& $first_abs;
+ $smaller =& $second_abs;
+ }
+ else
+ {
+ $bigger =& $second_abs;
+ $smaller =& $first_abs;
+ }
+ $smaller = $bigger + $smaller;
+ }
+
+ return ($first_abs > $second_abs) ? 1 : ($first_abs < $second_abs ? -1 : 0);
+ }
+
+ /**
+ * Searches through submitted grid data to find record with specific value in specific field
+ *
+ * @param Array $records // grid data from REQUEST
+ * @param string $field
+ * @param string $value
+ * @return bool
+ */
+ function arraySearch($records, $field, $value) // check_array
+ {
+ foreach ($records as $record)
+ {
+ if ($record[$field] == $value)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Replate infinity mark with -1 before saving to db
+ *
+ * @param kEvent $event
+ */
+ function replaceInfinity(&$event)
+ {
+ $object =& $event->getObject();
+ if($object->GetDBField($this->max_field) == '&#8734;') $object->SetDBField($this->max_field, -1);
+ }
+
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/brackets_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.4.26.2
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/custom_fields_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/custom_fields_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/custom_fields_helper.php (revision 12306)
@@ -0,0 +1,130 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ /**
+ * Enter description here...
+ *
+ * @todo rewrite
+ */
+ class InpCustomFieldsHelper extends kHelper {
+
+ /**
+ * Parses given option string and returns associative array
+ *
+ * @param string $values_list
+ * @param string $separator
+ * @param bool $parse
+ * @return Array
+ */
+ function GetValuesHash($values_list, $separator = VALUE_LIST_SEPARATOR, $parse = true)
+ {
+ $values_list = trim($this->ParseConfigSQL($values_list, $separator, $parse), $separator);
+
+ if (!$values_list) {
+ // no options, then return empty array
+ return Array();
+ }
+
+ $optionValuesTmp = explode($separator, $values_list);
+ $optionValues = Array();
+
+ if (substr_count($values_list, '=') != count($optionValuesTmp)) {
+ if ($this->Application->isDebugMode()) {
+ $this->Application->Debugger->appendTrace();
+ }
+
+ trigger_error('Invalid symbol in ValueList field [' . substr($values_list, 0, 100) . ' ...]' , E_USER_NOTICE);
+ return Array ();
+ }
+
+ if ($parse) {
+ // normal way
+ foreach ($optionValuesTmp as $optionValue) {
+ list ($key, $val) = explode('=', $optionValue);
+
+ $val = substr($val, 0, 1) == '+' ? substr($val, 1) : $this->Application->Phrase($val);
+
+ $optionValues[$key] = $val;
+ }
+ }
+ else {
+ // during custom field editing
+ foreach ($optionValuesTmp as $optionValue) {
+ list ($key, $val) = explode('=', $optionValue);
+
+ if (substr($key, 0, 3) == 'SQL') {
+ $val = base64_decode( str_replace('_', '=', substr($val, 1)) );
+ }
+
+ $optionValues[$key] = $val;
+ }
+ }
+
+ return $optionValues;
+ }
+
+ /**
+ * Replace SQL's in valueList with appropriate queried values
+ *
+ * @param string $valueString
+ * @param string $separator
+ * @return string
+ * @todo Apply refactoring to embedded vars stuff
+ */
+ function ParseConfigSQL($valueString, $separator = VALUE_LIST_SEPARATOR, $parse_sqls = true)
+ {
+ $string = trim( str_replace(Array('<PREFIX>', '%3$s'), Array (TABLE_PREFIX, $this->Application->GetVar('m_lang')), $valueString) );
+
+ if (preg_match_all('/<SQL([+]{0,1})>(.*?)<\/SQL>/', $string, $regs)) {
+ $i = 0;
+ $sql_count = count($regs[0]);
+ while ($i < $sql_count) {
+ if ($parse_sqls) {
+ $replacement = $this->_queryConfigSQL($regs[2][$i], $regs[1][$i], $separator);
+ }
+ else {
+ $sql = base64_encode('<SQL'.$regs[1][$i].'>'.$regs[2][$i].'</SQL>');
+ $replacement = 'SQL' . $i . '=+' . str_replace('=', '_', $sql);
+ }
+
+ $string = str_replace('<SQL'.$regs[1][$i].'>'.$regs[2][$i].'</SQL>', $replacement, $string);
+ $i++;
+ }
+
+ $string = preg_replace('/[' . preg_quote($separator, '/') . ']+/', $separator, $string); // trim trailing separators inside string
+ }
+
+ return $string;
+ }
+
+ /**
+ * Transforms given sql into value list string
+ *
+ * @param string $sql
+ * @param string $plus
+ * @param string $separator
+ * @return string
+ */
+ function _queryConfigSQL($sql, $plus = '', $separator = VALUE_LIST_SEPARATOR)
+ {
+ $values = $this->Conn->Query($sql);
+ foreach ($values as $index => $value) {
+ $values[$index] = $value['OptionValue'] . '=' . $plus . $value['OptionName'];
+ }
+
+ return implode($separator, $values);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/custom_fields_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.9.2.4
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/filenames_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/filenames_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/filenames_helper.php (revision 12306)
@@ -0,0 +1,158 @@
+<?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.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+class kFilenamesHelper extends kHelper {
+
+ /**
+ * Character, that should replace disallowed symbols in filename
+ *
+ * @var string
+ */
+ var $_escapeChar = '_';
+
+ /**
+ * Sequences, that should be replaced with mathing sequences from _filenameReplaceTo property
+ *
+ * @var Array
+ */
+ var $_filenameReplaceFrom = Array ();
+
+ /**
+ * Sequences, that will replace matching sequences from _filenameReplaceFrom property
+ *
+ * @var Array
+ */
+ var $_filenameReplaceTo = Array ();
+
+
+ function kFilenamesHelper()
+ {
+ parent::kHelper();
+
+ $this->_escapeChar = $this->Application->ConfigValue('FilenameSpecialCharReplacement');
+
+ $language =& $this->Application->recallObject('lang.current');
+ /* @var $language kDBItem */
+
+ $replacements = $language->GetDBField('FilenameReplacements');
+ if ($replacements) {
+ $replacements = explode("\r\n", $replacements);
+ foreach ($replacements as $replacement) {
+ list ($replace_from, $replace_to) = explode('=', $replacement);
+ $this->_filenameReplaceFrom[] = trim($replace_from);
+ $this->_filenameReplaceTo[] = trim($replace_to);
+ }
+ }
+ }
+
+ function replaceSequences($filename)
+ {
+ $not_allowed = Array (
+ ' ', '\\', '/', ':', '*', '?', '"', '<', '>', '|', '`',
+ '~', '!', '@', '#', '$', '%', '^', '&', '(', ')', '~',
+ '+', '=', '-', '{', '}', ']', '[', "'", ';', '.', ',', "\r", "\n"
+ );
+
+ if ($this->_filenameReplaceFrom) {
+ // replace predefined sequences
+ $filename = str_replace($this->_filenameReplaceFrom, $this->_filenameReplaceTo, $filename);
+ }
+
+ $filename = str_replace($not_allowed, $this->_escapeChar, $filename);
+ $filename = preg_replace('/(' . $this->_escapeChar . '+)/', $this->_escapeChar, $filename);
+ return trim($filename, $this->_escapeChar); // remove trailing escape chars
+ }
+
+ /**
+ * replace not allowed symbols with "_" chars + remove duplicate "_" chars in result
+ *
+ * @param string $string
+ * @return string
+ */
+ function stripDisallowed($table, $id_field, $item_id, $filename)
+ {
+ $filename = $this->replaceSequences($filename);
+
+ return $this->checkAutoFilename($table, $id_field, $item_id, $filename);
+ }
+
+ function checkAutoFilename($table, $id_field, $item_id, $filename)
+ {
+ if(!$filename) return $filename;
+
+ $item_id = !$item_id ? 0 : $item_id;
+
+ if ($table == TABLE_PREFIX.'CategoryItems') {
+ $item_categories_cur = $this->Conn->GetCol('SELECT CategoryId FROM '.$table.' WHERE ItemResourceId = '.$item_id);
+ $item_categories_live = $this->Application->IsTempTable($table) ? $this->Conn->GetCol('SELECT CategoryId FROM '.$this->Application->GetLiveName($table).' WHERE ItemResourceId = '.$item_id) : array();
+
+ $item_categories = array_unique(array_merge($item_categories_cur, $item_categories_live));
+ if (!$item_categories) {
+ $item_categories = array($this->Application->GetVar('m_cat_id')); // this may happen when creating new item
+ }
+ $cat_filter = ' AND CategoryId IN ('.implode(',', $item_categories).')';
+ }
+ else {
+ $cat_filter = '';
+ }
+
+ // check current table (temp or live)
+ $sql_temp = 'SELECT '.$id_field.' FROM '.$table.' WHERE Filename = '.$this->Conn->qstr($filename).$cat_filter;
+ $found_temp_ids = $this->Conn->GetCol($sql_temp);
+
+ // check live table if current is temp
+ if ( $this->Application->IsTempTable($table) ) {
+ $sql_live = 'SELECT '.$id_field.' FROM '.$this->Application->GetLiveName($table).' WHERE Filename = '.$this->Conn->qstr($filename).$cat_filter;
+ $found_live_ids = $this->Conn->GetCol($sql_live);
+ }
+ else {
+ $found_live_ids = array();
+ }
+
+ $found_item_ids = array_unique( array_merge($found_temp_ids, $found_live_ids) );
+
+ $has_page = preg_match('/(.*)_([\d]+)([a-z]*)$/', $filename, $rets);
+
+ $duplicates_found = (count($found_item_ids) > 1) || ($found_item_ids && $found_item_ids[0] != $item_id);
+ if ($duplicates_found || $has_page) // other category has same filename as ours OR we have filename, that ends with _number
+ {
+ $append = $duplicates_found ? '_a' : '';
+ if($has_page)
+ {
+ $filename = $rets[1].'_'.$rets[2];
+ $append = $rets[3] ? $rets[3] : '_a';
+ }
+
+ // check live & temp table
+ $sql_cur = 'SELECT '.$id_field.' FROM '.$table.' WHERE (Filename = %s) AND ('.$id_field.' != '.$item_id.')'.$cat_filter;
+ $sql_live = $this->Application->IsTempTable($table) ? 'SELECT '.$id_field.' FROM '.$this->Application->GetLiveName($table).' WHERE (Filename = %s) AND ('.$id_field.' != '.$item_id.')'.$cat_filter : false;
+ while ( $this->Conn->GetOne( sprintf($sql_cur, $this->Conn->qstr($filename.$append)) ) > 0 ||
+ ( $sql_live
+ &&
+ ( $this->Conn->GetOne( sprintf($sql_live, $this->Conn->qstr($filename.$append)) ) > 0 )
+ )
+ )
+ {
+ if (mb_substr($append, -1) == 'z') $append .= 'a';
+ $append = mb_substr($append, 0, mb_strlen($append) - 1) . chr( ord( mb_substr($append, -1) ) + 1 );
+ }
+
+ return $filename.$append;
+ }
+
+ return $filename;
+ }
+}
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/filenames_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.3.2.2
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/captcha_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/captcha_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/captcha_helper.php (revision 12306)
@@ -0,0 +1,176 @@
+<?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.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+class kCaptchaHelper extends kHelper {
+
+ var $width;
+ var $height;
+
+ function GenerateCaptchaCode($len = 5)
+ {
+ $chars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ $s = '';
+ for ($i = 0; $i < $len; $i++) {
+ $s .= $chars[ rand(0, strlen($chars)-1) ];
+ }
+ return $s;
+ }
+
+ function graphics($w, $h)
+ {
+ $this->width = $w;
+ $this->height = $h;
+ }
+
+ function GenerateCaptchaImage($rand, $width, $height, $filter_blur = false)
+ {
+ global $site_font_path;
+ global $site_font_validation;
+
+ $image = imagecreate($width, $height);
+ $bgColor = imagecolorallocate ($image, 255, 255, 255);
+ $textColor = imagecolorallocate ($image, 0, 0, 0);
+
+ // add random noise
+ for ($i = 0; $i < 20; $i++) {
+ $rx1 = rand(0, $width);
+ $rx2 = rand(0, $width);
+ $ry1 = rand(0, $height);
+ $ry2 = rand(0, $height);
+ $rcVal = rand(0, 255);
+ $rc1 = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(100, 255));
+ imageline($image, $rx1, $ry1, $rx2, $ry2, $rc1);
+ }
+
+ // write the random number
+
+ $dimensions = imagettfbbox($height*0.75, 0, KERNEL_PATH.'/fonts/monofont.ttf', $rand );
+
+ imagettftext($image, $height*0.75, 0, floor(($width - $dimensions[4])/2), floor(($height - $dimensions[5])/2), $textColor, KERNEL_PATH.'/fonts/monofont.ttf', $rand);
+
+ // $font = imageloadfont(KERNEL_PATH.'/fonts/monofont.ttf');
+ // imagestring($image, $font, 3, 0, $rand, $textColor);
+
+ if ($filter_blur) $this->blur($image, 3);
+
+ // send several headers to make sure the image is not cached
+ // date in the past
+ header("Expires: Mon, 23 Jul 1993 05:00:00 GMT");
+
+ // always modified
+ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+
+ // HTTP/1.1
+ header("Cache-Control: no-store, no-cache, must-revalidate");
+ header("Cache-Control: post-check=0, pre-check=0", false);
+
+ // HTTP/1.0
+ header("Pragma: no-cache");
+
+ // send the content type header so the image is displayed properly
+ header('Content-type: image/jpeg');
+
+ imagejpeg($image);
+ imagedestroy($image);
+ }
+
+ function blur(&$gdimg, $radius = 5.0)
+ {
+ // Taken from Torstein H�nsi's phpUnsharpMask (see phpthumb.unsharp.php)
+
+ $radius = round(max(0, min($radius, 50)) * 2);
+ if (!$radius) {
+ return false;
+ }
+
+ $w = ImageSX($gdimg);
+ $h = ImageSY($gdimg);
+ if ($imgBlur = ImageCreateTrueColor($w, $h)) {
+ // Gaussian blur matrix:
+ // 1 2 1
+ // 2 4 2
+ // 1 2 1
+
+ // Move copies of the image around one pixel at the time and merge them with weight
+ // according to the matrix. The same matrix is simply repeated for higher radii.
+ for ($i = 0; $i < $radius; $i++) {
+ ImageCopy ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1); // up left
+ ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w, $h, 50.00000); // down right
+ ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left
+ ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w, $h - 1, 25.00000); // up right
+ ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left
+ ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w, $h, 25.00000); // right
+ ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w, $h - 1, 20.00000); // up
+ ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w, $h, 16.666667); // down
+ ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w, $h, 50.000000); // center
+ ImageCopy ($gdimg, $imgBlur, 0, 0, 0, 0, $w, $h);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Generates captcha code for showing on form
+ *
+ * @param kEvent $event
+ */
+ function prepareCode(&$event)
+ {
+ if ($this->Application->IsAdmin() || $this->Application->RecallVar($event->getPrefixSpecial() . '_captcha_code')) {
+ // when code found don't generate it 2nd time
+ return ;
+ }
+
+ $this->Application->StoreVar($event->getPrefixSpecial() . '_captcha_code', $this->GenerateCaptchaCode());
+ }
+
+ /**
+ * Validates captcha code on form
+ *
+ * @param kEvent $event
+ * @param bool $check_request
+ * @return bool
+ */
+ function validateCode(&$event, $check_request = true)
+ {
+ if ($this->Application->IsAdmin()) {
+ // no captcha codes in admin
+ return true;
+ }
+
+ if ($check_request) {
+ // perform validation only when field is found on form
+ list ($id, $field_values) = each($this->Application->GetVar($event->getPrefixSpecial()));
+ if (!array_key_exists('Captcha', $field_values)) {
+ // when captcha code not submitted
+ return true;
+ }
+ }
+
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ if ($object->GetDBField('Captcha') != $this->Application->RecallVar($event->getPrefixSpecial() . '_captcha_code')) {
+ $object->SetError('Captcha', 'captcha_error', 'lu_captcha_error');
+
+ $this->Application->StoreVar($event->getPrefixSpecial() . '_captcha_code', $this->GenerateCaptchaCode());
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/captcha_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.3.2.1
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/recursive_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/recursive_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/recursive_helper.php (revision 12306)
@@ -0,0 +1,223 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kRecursiveHelper extends kHelper {
+
+ function DeleteCategory($category_id, $prefix='c')
+ {
+ $id_field = $this->Application->getUnitOption($prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+
+ $sql = 'SELECT '.$id_field.'
+ FROM '.$table_name.'
+ WHERE ParentId = '.$category_id;
+
+ $sub_categories = $this->Conn->GetCol($sql);
+ if ($sub_categories) {
+ foreach ($sub_categories as $sub_category_id) {
+ $this->DeleteCategory($sub_category_id);
+ }
+ }
+
+ $ci_table = $this->Application->getUnitOption('ci', 'TableName');
+ // 1. remove category items from this category if it is supplemental (non-primary) category to them
+ $sql = 'DELETE FROM '.$ci_table.'
+ WHERE ('.$id_field.' = '.$category_id.') AND (PrimaryCat = 0)';
+ $this->Conn->Query($sql);
+
+ $temp_handler =& $this->Application->recallObject($prefix.'_TempHandler', 'kTempTablesHandler');
+
+ // 2. delete items this have this category as primary
+ $delete_ids = $this->getCategoryItems($category_id, true);
+
+ foreach ($delete_ids as $item_prefix => $resource_ids) {
+ if (!$item_prefix) {
+ // not ItemPrefix filled -> old categoryitem linking
+ continue;
+ }
+ $item_ids = $this->GetItemIDs($item_prefix, $resource_ids);
+ $temp_handler->BuildTables($item_prefix, $item_ids);
+ $temp_handler->DeleteItems($item_prefix, '', $item_ids);
+ }
+
+ // 3. delete this category
+ $temp_handler->BuildTables($prefix, Array($category_id));
+ $temp_handler->DeleteItems($prefix, '', Array($category_id));
+ }
+
+ /**
+ * Converts resource ids list to id field list for given prefix
+ *
+ * @param string $prefix
+ * @param Array $resource_ids
+ * @return Array
+ */
+ function GetItemIDs($prefix, $resource_ids)
+ {
+ if (!$resource_ids) {
+ return Array();
+ }
+
+ $id_field = $this->Application->getUnitOption($prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+
+ $sql = 'SELECT '.$id_field.'
+ FROM '.$table_name.'
+ WHERE ResourceId IN ('.implode(',', $resource_ids).')';
+ return $this->Conn->GetCol($sql);
+ }
+
+ // moves selected categories to destination category
+ function MoveCategories($category_ids, $dest_category_id)
+ {
+ if (!$category_ids) return ;
+
+ $id_field = $this->Application->getUnitOption('c', 'IDField');
+ $table_name = $this->Application->getUnitOption('c', 'TableName');
+
+ // do not move categories into their children
+ $sql = 'SELECT ParentPath
+ FROM '.$table_name.'
+ WHERE '.$id_field.' = '.$dest_category_id;
+ $dest_parent_path = explode('|', substr($this->Conn->GetOne($sql), 1, -1));
+
+ $child_categories = array_intersect($dest_parent_path, $category_ids); // get categories, then can't be moved
+ $category_ids = array_diff($category_ids, $child_categories); // remove them from movable categories list
+
+ if ($category_ids) {
+ $sql = 'UPDATE '.$table_name.'
+ SET ParentId = '.$dest_category_id.'
+ WHERE '.$id_field.' IN ('.implode(',', $category_ids).')';
+ $this->Conn->Query($sql);
+ }
+ }
+
+ /**
+ * Complete cloning or category with subcategories and subitems
+ *
+ * @param int $category_id
+ */
+ function PasteCategory($category_id, $prefix = 'c')
+ {
+ $backup_category_id = $this->Application->GetVar('m_cat_id');
+
+ $src_parent_path = $this->_getParentPath($category_id);
+ $dst_parent_path = $this->_getParentPath($backup_category_id);
+
+ if (substr($dst_parent_path, 0, strlen($src_parent_path)) == $src_parent_path) {
+ // target path contains source path -> recursion
+ return ;
+ }
+
+ // 1. clone category
+ $temp_handler =& $this->Application->recallObject($prefix.'_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler*/
+ $temp_handler->BuildTables($prefix, Array($category_id));
+ $new_category_id = array_pop( $temp_handler->CloneItems($prefix, '', Array($category_id)) );
+ $this->Application->SetVar('m_cat_id', $new_category_id);
+
+ $id_field = $this->Application->getUnitOption($prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+
+ // 2. assign supplemental items to current category to new category
+ $paste_ids = $this->getCategoryItems($category_id, false);
+
+ foreach ($paste_ids as $item_prefix => $resource_ids) {
+ if (!$item_prefix) {
+ // not ItemPrefix filled -> old categoryitem linking
+ continue;
+ }
+
+ $item_object =& $this->Application->recallObject($item_prefix.'.-item', null, Array('skip_autoload' => true));
+ foreach ($resource_ids as $item_resource_id) {
+ $item_object->Load($item_resource_id, 'ResourceId');
+ $item_object->assignToCategory($new_category_id, false);
+ }
+ }
+
+ // 3. clone items that have current category as primary
+ $paste_ids = $this->getCategoryItems($category_id, true);
+
+ foreach ($paste_ids as $item_prefix => $resource_ids) {
+ if (!$item_prefix) {
+ // not ItemPrefix filled -> old categoryitem linking
+ continue;
+ }
+
+ // 2. clone items from current category (for each prefix separately)
+ $item_ids = $this->GetItemIDs($item_prefix, $resource_ids);
+ $temp_handler->BuildTables($item_prefix, $item_ids);
+ $temp_handler->CloneItems($item_prefix, '', $item_ids);
+ }
+
+ // 4. do same stuff for each subcategory
+ $sql = 'SELECT '.$id_field.'
+ FROM '.$table_name.'
+ WHERE ParentId = '.$category_id;
+
+ $sub_categories = $this->Conn->GetCol($sql);
+ if ($sub_categories) {
+ foreach ($sub_categories as $sub_category_id) {
+ $this->PasteCategory($sub_category_id, $prefix);
+ }
+ }
+
+ $this->Application->SetVar('m_cat_id', $backup_category_id);
+ }
+
+ /**
+ * Returns grouped category items
+ *
+ * @param int $category_id
+ * @param bool $item_primary_category
+ * @return Array
+ */
+ function getCategoryItems($category_id, $item_primary_category = true)
+ {
+ $ci_table = $this->Application->getUnitOption('ci', 'TableName');
+
+ $sql = 'SELECT ItemPrefix, ItemResourceId
+ FROM '.$ci_table.'
+ WHERE (CategoryId = '.$category_id.') AND (PrimaryCat = '.($item_primary_category ? 1 : 0).')';
+ $category_items = $this->Conn->GetCol($sql, 'ItemResourceId');
+
+ $item_ids = Array();
+ foreach ($category_items as $resource_id => $item_prefix) {
+ $item_ids[$item_prefix][] = $resource_id;
+ }
+ return $item_ids;
+ }
+
+ /**
+ * Returns parent path for given category
+ *
+ * @param int $category_id
+ * @return Array
+ */
+ function _getParentPath($category_id)
+ {
+ static $cache = Array ();
+
+ if (!array_key_exists($category_id, $cache)) {
+ $sql = 'SELECT ParentPath
+ FROM ' . TABLE_PREFIX . 'Category
+ WHERE CategoryId = ' . $category_id;
+ $cache[$category_id] = $this->Conn->GetOne($sql);
+ }
+
+ return $cache[$category_id];
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/recursive_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.6
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/permissions_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/permissions_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/permissions_helper.php (revision 12306)
@@ -0,0 +1,680 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kPermissionsHelper extends kHelper {
+
+ /**
+ * Current set of permissions for group being edited
+ *
+ * @var Array
+ */
+ var $Permissions = Array();
+
+ function LoadPermissions($group_id, $cat_id, $type = 1, $prefix = '')
+ {
+ $perm_table = $this->Application->getUnitOption('perm', 'TableName');
+ $perm_table = $this->Application->GetTempName($perm_table, 'prefix:'.$prefix);
+ $sql = 'SELECT *
+ FROM '.$perm_table.'
+ WHERE (GroupId = '.$group_id.') AND (CatId = '.$cat_id.') AND (Type = '.$type.')';
+ $permissions = $this->Conn->Query($sql, 'Permission');
+
+ $this->Permissions = Array();
+ foreach ($permissions as $perm_name => $perm_options) {
+ $perm_record['value'] = $perm_options['PermissionValue'];
+ $perm_record['id'] = $perm_options['PermissionId'];
+ $this->Permissions[$perm_name] = $perm_record;
+ }
+ }
+
+ function getPermissionValue($perm_name)
+ {
+ return isset($this->Permissions[$perm_name]) ? $this->Permissions[$perm_name]['value'] : 0;
+ }
+
+ function getPermissionID($perm_name)
+ {
+ return isset($this->Permissions[$perm_name]) ? $this->Permissions[$perm_name]['id'] : 0;
+ }
+
+ /**
+ * This is old permission like ADMIN or LOGIN
+ *
+ * @param string $section_name
+ * @param string $perm_name
+ * @return bool
+ */
+ function isOldPermission($section_name, $perm_name)
+ {
+ return $section_name == 'in-portal:root' && $perm_name != 'view';
+ }
+
+ /**
+ * Returns permission names to check based on event name and item prefix (main item or subitem)
+ *
+ * @param kEvent $event
+ * @return Array
+ */
+ function getPermissionByEvent(&$event, $perm_mapping)
+ {
+ $top_prefix = $event->getEventParam('top_prefix');
+
+ $pefix_type = ($top_prefix == $event->Prefix) ? 'self' : 'subitem';
+ $perm_mapping = getArrayValue($perm_mapping, $event->Name);
+
+ if (!$perm_mapping[$pefix_type]) {
+ trigger_error('Permission mappings not defined for event <b>'.$top_prefix.' <- '.$event->Prefix.':'.$event->Name.'</b>', E_USER_ERROR);
+ }
+
+ if ($perm_mapping[$pefix_type] === true) {
+ // event is defined in mapping but is not checked by permissions
+ return true;
+ }
+
+ return explode('|', $perm_mapping[$pefix_type]);
+ }
+
+ /**
+ * Common event permission checking method
+ *
+ * @param kEvent $event
+ */
+ function CheckEventPermission(&$event, $perm_mapping)
+ {
+ $section = $event->getSection();
+ if (preg_match('/^CATEGORY:(.*)/', $section)) {
+ return $this->CheckEventCategoryPermission($event, $perm_mapping);
+ }
+
+ $top_prefix = $event->getEventParam('top_prefix');
+ $check_perms = $this->getPermissionByEvent($event, $perm_mapping);
+
+ if ($check_perms === true) {
+ // event is defined in mapping but is not checked by permissions
+ return true;
+ }
+
+ $perm_status = false;
+ foreach ($check_perms as $perm_name) {
+ // check if at least one of required permissions is set
+ $perm_name = $section.'.'.$perm_name;
+ $perm_status = $this->CheckPermission($perm_name, 1);
+ if (($perm_name == $section.'.add') && $perm_status && ($top_prefix == $event->Prefix)) {
+ // main item, add permission allowed, but ID is > 0, then deny permission
+ // how to get id here
+ }
+
+ if ($perm_status) {
+ return $perm_status;
+ }
+ }
+
+ return $this->finalizePermissionCheck($event, $perm_status);
+ }
+
+ /**
+ * Returns owner + primary category for each item (used for permission checking)
+ *
+ * @param string $prefix
+ * @param string $ids
+ * @param bool $temp_mode
+ * @return Array
+ * @author Alex
+ */
+ function GetCategoryItemData($prefix, $ids, $temp_mode = false)
+ {
+ if (is_array($ids)) {
+ $ids = implode(',', $ids);
+ }
+ $id_field = $this->Application->getUnitOption($prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+ $ci_table = $this->Application->getUnitOption('ci', 'TableName');
+
+ if ($temp_mode) {
+ $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $prefix);
+ $ci_table = $this->Application->GetTempName($ci_table, 'prefix:' . $prefix);
+ }
+
+ $owner_field = $this->Application->getUnitOption($prefix, 'OwnerField');
+ if (!$owner_field) {
+ $owner_field = 'CreatedById';
+ }
+
+ $sql = 'SELECT item_table.'.$id_field.', item_table.'.$owner_field.' AS CreatedById, ci.CategoryId
+ FROM '.$table_name.' item_table
+ LEFT JOIN '.$ci_table.' ci ON ci.ItemResourceId = item_table.ResourceId
+ WHERE item_table.'.$id_field.' IN ('.$ids.') AND (ci.PrimaryCat = 1)';
+ return $this->Conn->Query($sql, $id_field);
+ }
+
+ /**
+ * Check category-based permissions for category items
+ *
+ * @param kEvent $event
+ */
+ function _frontCheckEventCategoryPermission(&$event, $event_perm_mapping)
+ {
+ // mapping between specific permissions and common permissions
+ static $perm_mapping = Array(
+ 'add' => 'ADD', 'add.pending' => 'ADD.PENDING', 'edit' => 'MODIFY',
+ 'edit.pending' => 'MODIFY.PENDING', 'delete' => 'DELETE', 'view' => 'VIEW'
+ );
+
+ $top_prefix = $event->getEventParam('top_prefix');
+ $event_handler =& $this->Application->recallObject($event->Prefix.'_EventHandler');
+ /* @var $event_handler kCatDBEventHandler */
+
+ $raise_warnings = $event->getEventParam('raise_warnings');
+ $event->setEventParam('raise_warnings', 0);
+ if ($event->Prefix != $top_prefix) {
+ $top_event = new kEvent($top_prefix.':'.$event->Name);
+ $id = $event_handler->getPassedID($top_event);
+ }
+ else {
+ $id = $event_handler->getPassedID($event);
+ }
+ $event->setEventParam('raise_warnings', $raise_warnings);
+
+ $owner_id = -1; // owner is root if not detected
+ if (!$id) {
+ // item being created -> check by current (before editing started, saved in OnPreCreate event) category permissions
+ // note: category in session is placed on catalog data import start
+ $category_id = $this->Application->IsAdmin() ? $this->Application->RecallVar('m_cat_id') : $this->Application->GetVar('m_cat_id');
+ }
+ elseif ($top_prefix == 'c' || $top_prefix == 'st') {
+ $category_id = $id;
+ }
+ else {
+ // item being edited -> check by it's primary category permissions
+ $items_info = $this->GetCategoryItemData($top_prefix, $id);
+ $category_id = $items_info[$id]['CategoryId'];
+ $owner_id = $items_info[$id]['CreatedById'];
+ }
+
+ // specific permission check for pending & owner permissions: begin
+ $uploader_events = Array ('OnUploadFile', 'OnDeleteFile', 'OnViewFile');
+ if (in_array($event->Name, $uploader_events)) {
+ // don't recall target object during uploader-related, because OnItemLoad will use incorrect
+ // $user_id in Firefox (during Flash problems session will be used from Internet Exploere)
+ $new_item = false;
+ }
+ else {
+ $new_item = $this->Application->IsAdmin() && $event_handler->isNewItemCreate($event) ? true : false;
+ $check_status = $this->checkCombinedPermissions($event, $owner_id, (int)$category_id, $new_item);
+ }
+
+ if (isset($check_status)) {
+ return $this->finalizePermissionCheck($event, $check_status);
+ }
+ // specific permission check for pending & owner permissions: end
+
+ $perm_status = false;
+ $check_perms = $this->getPermissionByEvent($event, $event_perm_mapping);
+
+ if ($check_perms === true) {
+ // event is defined in mapping but is not checked by permissions
+ return true;
+ }
+
+ $item_prefix = $this->Application->getUnitOption($top_prefix, 'PermItemPrefix');
+ foreach ($check_perms as $perm_name) {
+ // check if at least one of required permissions is set
+ if (!isset($perm_mapping[$perm_name])) {
+ // not mapped permission (e.g. advanced:approve) -> skip
+ continue;
+ }
+ $perm_name = $item_prefix.'.'.$perm_mapping[$perm_name];
+ $perm_status = $this->CheckPermission($perm_name, 0, (int)$category_id);
+
+ if ($perm_status) {
+ return $perm_status;
+ }
+ }
+
+ return $this->finalizePermissionCheck($event, $perm_status);
+ }
+
+ /**
+ * Finalizes permission checking (with additional debug output, when in debug mode)
+ *
+ * @param kEvent $event
+ * @param bool $perm_status
+ * @return bool
+ */
+ function finalizePermissionCheck(&$event, $perm_status)
+ {
+ if (!$perm_status) {
+ if ($this->Application->isDebugMode()) {
+ // for debugging purposes
+ $event->SetRedirectParam('section', $event->getSection());
+ $event->SetRedirectParam('main_prefix', $event->getEventParam('top_prefix'));
+ $event->SetRedirectParam('event_name', $event->Name);
+ $event->SetRedirectParam('next_template', $this->Application->GetVar('t'));
+ }
+
+ $event->status = erPERM_FAIL;
+ }
+
+ return $perm_status;
+ }
+
+ /**
+ * Allows to check combined permissions (*.owner, *.pending) for add/modify/delete operations from admin & front-end
+ *
+ * @param kEvent $event
+ * @param int $owner_id
+ * @param int $category_id
+ * @param bool $new_item
+ * @return mixed
+ */
+ function checkCombinedPermissions(&$event, $owner_id, $category_id, $new_item = false)
+ {
+ $ret = null; // true/false when used, null when not used
+ $top_prefix = $event->getEventParam('top_prefix');
+
+ // check admin permission
+ if (substr($event->Name, 0, 9) == 'OnPreSave') {
+ if ($new_item) {
+ $ret = $this->AddCheckPermission($category_id, $top_prefix);
+ }
+ else {
+ // add & modify because $new_item is false, when item is aready created & then saved in temp table (even with 0 id)
+ $ret = $this->AddCheckPermission($category_id, $top_prefix) ||
+ $this->ModifyCheckPermission($owner_id, $category_id, $top_prefix);
+ }
+ }
+
+ // check front-end permissions
+ switch ($event->Name) {
+ case 'OnCreate':
+ $ret = $this->AddCheckPermission($category_id, $top_prefix);
+ break;
+
+ case 'OnUpdate':
+ $ret = $this->ModifyCheckPermission($owner_id, $category_id, $top_prefix);
+ break;
+
+ case 'OnDelete':
+ case 'OnMassDelete':
+ $ret = $this->DeleteCheckPermission($owner_id, $category_id, $top_prefix);
+ break;
+ }
+
+ if ($ret === 0) {
+ // permission check failed (user has no permission)
+ $event->status = erPERM_FAIL;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Simplified permission check for category items, when adding/editing them from advanced view.
+ *
+ * @param kEvent $event
+ * @return mixed
+ */
+ function CheckEventCategoryPermission(&$event, $event_perm_mapping)
+ {
+ if (!$this->Application->IsAdmin()) {
+ // check front-end permission by old scheme
+ return $this->_frontCheckEventCategoryPermission($event, $event_perm_mapping);
+ }
+
+ if (substr($event->Name, 0, 9) == 'OnPreSave') {
+ // check separately, because permission mapping is not defined for OnPreSave* events
+ $check_perms = Array ('add', 'edit');
+ }
+ else {
+ $check_perms = $this->getPermissionByEvent($event, $event_perm_mapping);
+ }
+
+ if ($check_perms === true) {
+ // event is defined in mapping but is not checked by permissions
+ return true;
+ }
+
+ // 1. most of events does require admin login only
+ $perm_status = $this->Application->LoggedIn() && $this->Application->IsAdmin();
+
+ // 2. in case, when event require more, then "view" right, then restrict it to temporary tables only
+ if (!in_array('view', $check_perms)) {
+ $perm_status = $perm_status && $this->Application->IsTempMode($event->Prefix, $event->Special);
+ }
+
+ return $this->finalizePermissionCheck($event, $perm_status);
+ }
+
+ function TagPermissionCheck($params, $is_owner = false)
+ {
+ $perm_prefix = getArrayValue($params, 'perm_prefix');
+ $perm_event = getArrayValue($params, 'perm_event');
+ $permission_groups = getArrayValue($params, 'permissions');
+
+ if ($permission_groups && !$perm_event) {
+ // check permissions by permission names in current category
+ $permission_groups = explode('|', $permission_groups);
+ $group_has_permission = false;
+
+ $perm_category = isset($params['cat_id']) ? $params['cat_id'] : $this->Application->GetVar('m_cat_id');
+
+ if ($perm_prefix) {
+ // use primary category of item with id from {perm_prefix}_id as base for permission checking
+ $perm_category = $this->getPrimaryCategory($perm_prefix);
+ }
+
+ $is_system = isset($params['system']) && $params['system'] ? 1 : 0;
+ foreach ($permission_groups as $permission_group) {
+ $permissions = explode(',', $permission_group);
+ $has_permission = true;
+ foreach ($permissions as $permission) {
+ $owner_checked = (strpos($permission, '.OWNER.') !== false) ? $is_owner : true;
+ $has_permission = $has_permission && $this->CheckPermission($permission, $is_system, $perm_category) && $owner_checked;
+ }
+ $group_has_permission = $group_has_permission || $has_permission;
+
+ if ($group_has_permission) {
+ return true;
+ }
+ }
+ return false;
+ }
+ elseif ($perm_event) {
+ // check permission by event name
+ list ($prefix, $event) = explode(':', $perm_event);
+ $event_handler =& $this->Application->recallObject($prefix.'_EventHandler');
+ return $event_handler->CheckPermission( new kEvent($perm_event) );
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns item's primary category (get item_id from request)
+ *
+ * @param string $prefix
+ * @return int
+ */
+ function getPrimaryCategory($prefix)
+ {
+ $id_field = $this->Application->getUnitOption($prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+ $id = $this->Application->GetVar($prefix.'_id');
+
+ if (!$id) return $this->Application->GetVar('m_cat_id');
+
+ $sql = 'SELECT ResourceId
+ FROM '.$table_name.'
+ WHERE '.$id_field.' = '.$id;
+ $resource_id = $this->Conn->GetOne($sql);
+
+ $sql = 'SELECT CategoryId
+ FROM '.$this->Application->getUnitOption('ci', 'TableName').'
+ WHERE ItemResourceId = '.$resource_id.' AND PrimaryCat = 1';
+ return $this->Conn->GetOne($sql);
+ }
+
+ /**
+ * Returns no permission template to redirect to
+ *
+ * @param Array $params
+ * @return Array
+ */
+ function getPermissionTemplate($params)
+ {
+ $t = $this->Application->GetVar('t');
+ if ($next_t = getArrayValue($params, 'next_template')) {
+ $t = $next_t;
+ }
+
+ $redirect_params = $this->Application->HttpQuery->getRedirectParams(true);
+
+ if (array_key_exists('pass_category', $params)) {
+ $redirect_params['pass_category'] = $params['pass_cateogry'];
+ }
+
+ if (!$this->Application->LoggedIn()) {
+ $redirect_template = array_key_exists('login_template', $params) ? $params['login_template'] : '';
+ if (!$redirect_template && $this->Application->IsAdmin()) {
+ $redirect_template = 'login';
+ }
+ $redirect_params['next_template'] = $t;
+ }
+ else {
+ if (isset($params['no_permissions_template'])) {
+ $redirect_template = $params['no_permissions_template'];
+ }
+ else {
+ $redirect_template = $this->Application->IsAdmin() ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate');
+ }
+
+ if ($this->Application->isDebugMode()) {
+ $redirect_params['from_template'] = 1;
+ $redirect_params['perms'] = $params[ isset($params['permissions']) ? 'permissions' : 'perm_event' ];
+ $redirect_params['next_template'] = $t;
+ }
+ }
+
+ if (isset($params['index_file']) && $params['index_file']) {
+ $redirect_params['index_file'] = $params['index_file'];
+ }
+
+ return Array($redirect_template, $redirect_params);
+ }
+
+ /**
+ * Check current user permissions based on it's group permissions in specified category (for non-system permissions) or just checks if system permission is set
+ *
+ * @param string $name permission name
+ * @param int $cat_id category id, current used if not specified
+ * @param int $type permission type {1 - system, 0 - per category}
+ * @return int
+ */
+ function CheckPermission($name, $type = 1, $cat_id = null)
+ {
+ $user_id = $this->Application->RecallVar('user_id');
+ return $this->CheckUserPermission($user_id, $name, $type, $cat_id);
+ }
+
+ function CheckUserPermission($user_id, $name, $type = 1, $cat_id = null)
+ {
+ if ($user_id == -1) {
+ // "root" is allowed anywhere
+ return $name == 'SYSTEM_ACCESS.READONLY' ? 0 : 1;
+ }
+
+ if ($type == 1) {
+ // "system" permission are always checked per "Home" category (ID = 0)
+ $cat_id = 0;
+ }
+
+ if (!isset($cat_id)) {
+ $cat_id = $this->Application->GetVar('m_cat_id');
+ }
+
+ $cache_key = $name.'|'.$type.'|'.$cat_id;
+ $perm_value = $this->Application->getCache('permissions', $cache_key);
+ if ($perm_value !== false) {
+ return $perm_value;
+ }
+
+ // perm cache is build only based on records in db, that's why if permission is not explicitly denied, then
+ // that (perm cache creator) code thinks that it is allowed & adds corresponding record and code below will
+ // return incorrect results
+
+ if ($user_id == $this->Application->RecallVar('user_id')) {
+ $groups = explode(',', $this->Application->RecallVar('UserGroups'));
+ }
+ else { // checking not current user
+ $sql = 'SELECT GroupId
+ FROM '.TABLE_PREFIX.'UserGroup
+ WHERE (PortalUserId = '.$user_id.') AND ( (MembershipExpires IS NULL) OR ( MembershipExpires >= UNIX_TIMESTAMP() ) )';
+ $groups = $this->Conn->GetCol($sql);
+ array_push($groups, $this->Application->ConfigValue('User_LoggedInGroup') );
+ }
+
+ if (preg_match('/(.*)\.VIEW$/', $name) && ($type == 0)) {
+ // cached view permission of category: begin
+ if (strpos($cat_id, '|') !== false) {
+ $category_path = explode('|', substr($cat_id, 1, -1));
+ $cat_id = end($category_path);
+ }
+
+ $sql = 'SELECT PermissionConfigId
+ FROM '.TABLE_PREFIX.'PermissionConfig
+ WHERE PermissionName = '.$this->Conn->qstr($name);
+ $perm_id = $this->Conn->GetOne($sql);
+
+ $sql = 'SELECT PermId
+ FROM '.TABLE_PREFIX.'PermCache
+ WHERE (PermId = '.$perm_id.') AND (CategoryId = '.$cat_id.')';
+
+ $view_filters = Array();
+ foreach ($groups as $group) {
+ $view_filters[] = 'FIND_IN_SET('.$group.', ACL)';
+ }
+ $sql .= ' AND ('.implode(' OR ', $view_filters).')';
+ $perm_value = $this->Conn->GetOne($sql) ? 1 : 0;
+
+ $this->Application->setCache('permissions', $cache_key, $perm_value);
+ return $perm_value;
+ // cached view permission of category: end
+ }
+
+ if (is_numeric($cat_id) && $cat_id == 0) {
+ $cat_hierarchy = Array(0);
+ }
+ else {
+ if (strpos($cat_id, '|') !== false) {
+ $cat_hierarchy = $cat_id;
+ }
+ else {
+ $sql = 'SELECT ParentPath
+ FROM '.$this->Application->getUnitOption('c', 'TableName').'
+ WHERE CategoryId = '.$cat_id;
+ $cat_hierarchy = $this->Conn->GetOne($sql);
+ if ($cat_hierarchy === false) {
+ // category was deleted, but refrence to it stays in other tables -> data integrity is broken
+ $cat_hierarchy = '|' . $this->Application->findModule('Name', 'Core', 'RootCat') . '|';
+ }
+ }
+
+ $cat_hierarchy = explode('|', substr($cat_hierarchy, 1, -1));
+ $cat_hierarchy = array_reverse($cat_hierarchy);
+ array_push($cat_hierarchy, 0);
+ }
+
+ $perm_value = 0;
+ $groups = implode(',',$groups);
+ foreach ($cat_hierarchy as $category_id) {
+ $sql = 'SELECT SUM(PermissionValue)
+ FROM '.TABLE_PREFIX.'Permissions
+ WHERE Permission = "'.$name.'" AND CatId = '.$category_id.' AND GroupId IN ('.$groups.') AND Type = '.$type;
+ $res = $this->Conn->GetOne($sql);
+ if ($res !== false && !is_null($res)) {
+ $perm_value = $res ? 1 : 0;
+ break;
+ }
+ }
+
+ $this->Application->setCache('permissions', $cache_key, $perm_value);
+ return $perm_value;
+ }
+
+ /**
+ * Allows to check MODIFY & OWNER.MODFY +/- PENDING permission combinations on item
+ *
+ * @param int $owner_id user_id, that is owner of the item
+ * @param int $category_id primary category of item
+ * @param string $prefix prefix of item
+ * @return int {0 - no MODIFY permission, 1 - has MODIFY permission, 2 - has MODIFY.PENDING permission}
+ */
+ function ModifyCheckPermission($owner_id, $category_id, $prefix)
+ {
+ $perm_prefix = $this->Application->getUnitOption($prefix, 'PermItemPrefix');
+
+ $live_modify = $this->CheckPermission($perm_prefix.'.MODIFY', ptCATEGORY, $category_id);
+ if ($live_modify) {
+ return 1;
+ }
+ else if ($this->CheckPermission($perm_prefix.'.MODIFY.PENDING', ptCATEGORY, $category_id)) {
+ return 2;
+ }
+
+ if ($owner_id == $this->Application->RecallVar('user_id')) {
+ // user is item's OWNER -> check this permissions first
+ $live_modify = $this->CheckPermission($perm_prefix.'.OWNER.MODIFY', ptCATEGORY, $category_id);
+ if ($live_modify) {
+ return 1;
+ }
+ else if ($this->CheckPermission($perm_prefix.'.OWNER.MODIFY.PENDING', ptCATEGORY, $category_id)) {
+ return 2;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Allows to check DELETE & OWNER.DELETE permission combinations on item
+ *
+ * @param int $owner_id user_id, that is owner of the item
+ * @param int $category_id primary category of item
+ * @param string $prefix prefix of item
+ * @return int {0 - no DELETE permission, 1 - has DELETE/OWNER.DELETE permission}
+ */
+ function DeleteCheckPermission($owner_id, $category_id, $prefix)
+ {
+ $perm_prefix = $this->Application->getUnitOption($prefix, 'PermItemPrefix');
+
+ $live_delete = $this->CheckPermission($perm_prefix.'.DELETE', ptCATEGORY, $category_id);
+ if ($live_delete) {
+ return 1;
+ }
+
+ if ($owner_id == $this->Application->RecallVar('user_id')) {
+ // user is item's OWNER -> check this permissions first
+ $live_delete = $this->CheckPermission($perm_prefix.'.OWNER.DELETE', ptCATEGORY, $category_id);
+ if ($live_delete) {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Allows to check ADD +/- PENDING permission combinations on item
+ *
+ * @param int $category_id primary category of item
+ * @param string $prefix prefix of item
+ * @return int {0 - no ADD permission, 1 - has ADD permission, 2 - has ADD.PENDING permission}
+ */
+ function AddCheckPermission($category_id, $prefix)
+ {
+ $perm_prefix = $this->Application->getUnitOption($prefix, 'PermItemPrefix');
+
+ $live_add = $this->CheckPermission($perm_prefix.'.ADD', ptCATEGORY, $category_id);
+ if ($live_add) {
+ return 1;
+ }
+ else if ($this->CheckPermission($perm_prefix.'.ADD.PENDING', ptCATEGORY, $category_id)) {
+ return 2;
+ }
+
+ return 0;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/permissions_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.32.2.9
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/themes_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/themes_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/themes_helper.php (revision 12306)
@@ -0,0 +1,392 @@
+<?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.
+*/
+
+ 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 ();
+
+ function kThemesHelper()
+ {
+ parent::kHelper();
+ $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 ' . $id_field . ', Enabled
+ 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
+ $fields_hash = 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
+ );
+
+ $this->Conn->doInsert($fields_hash, $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);
+
+ return $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
+ */
+ function FindThemeFiles($folder_path, $theme_path, $theme_id, $auto_structure_mode = 1)
+ {
+ $fh = opendir($theme_path.$folder_path.'/');
+
+ // always ingore design and element templates
+ $ignore = Array ('^CVS$', '^\.svn$', '\.des\.tpl$', '\.elm\.tpl$');
+
+ $sms_ingore = $theme_path . $folder_path . '/.smsignore';
+
+ 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;
+ }
+ }
+
+ $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;
+
+ $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 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;
+ }
+ }
+ }
+
+ $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);
+
+ }
+
+ /**
+ * 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
+ * @return int
+ */
+ function getPageByTemplate($template)
+ {
+ $sql = 'SELECT ' . $this->Application->getUnitOption('c', 'IDField') . '
+ FROM ' . $this->Application->getUnitOption('c', 'TableName') . '
+ WHERE
+ (
+ (NamedParentPath = ' . $this->Conn->qstr('Content/' . $template) . ') OR
+ (IsSystem = 1 AND CachedTemplate = ' . $this->Conn->qstr($template) . ')
+ )
+ AND (ThemeId = ' . $this->getCurrentThemeId() . ' OR ThemeId = 0)';
+ return $this->Conn->GetOne($sql);
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/themes_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.4.2.5
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/sections_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/sections_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/sections_helper.php (revision 12306)
@@ -0,0 +1,306 @@
+<?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.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ /**
+ * Processes sections info from the configs
+ *
+ */
+ class kSectionsHelper extends kHelper {
+
+ /**
+ * Holds information about all sections
+ *
+ * @var Array
+ */
+ var $Tree = Array();
+
+ /**
+ * Set's prefix and special
+ *
+ * @param string $prefix
+ * @param string $special
+ * @access public
+ */
+ function Init($prefix, $special, $event_params = null)
+ {
+ parent::Init($prefix, $special, $event_params);
+ $this->BuildTree();
+ }
+
+ /**
+ * Builds xml for tree in left frame in admin
+ *
+ * @param Array $params
+ */
+ function BuildTree()
+ {
+ if (!isset($this->Application->Memcached) || !($data = $this->Application->Memcached->get('master:sections_parsed'))) {
+ $data = $this->Conn->GetOne('SELECT Data FROM '.TABLE_PREFIX.'Cache WHERE VarName = "sections_parsed"');
+ }
+ if ($data) {
+ $this->Tree = unserialize($data);
+ return ;
+ }
+
+ if (!(defined('IS_INSTALL') && IS_INSTALL)) {
+ // don't reread all configs during install, because they are reread on every install step
+ $this->Application->UnitConfigReader->ReReadConfigs();
+ }
+
+ $this->Tree = Array ();
+
+ // 1. build base tree (don't update parent with children list yet)
+
+ // 1.1. process prefixes without priority
+ $prioritized_prefixes = Array ();
+ $prefixes = array_keys($this->Application->UnitConfigReader->configData);
+
+ foreach ($prefixes as $prefix) {
+ $config =& $this->Application->UnitConfigReader->configData[$prefix];
+
+ if (array_key_exists('ConfigPriority', $config)) {
+ $prioritized_prefixes[$prefix] = $config['ConfigPriority'];
+ continue;
+ }
+ $this->_processPrefixSections($prefix);
+ }
+
+ // 2. process prefixes with priority
+ asort($prioritized_prefixes);
+ foreach ($prioritized_prefixes as $prefix => $priority) {
+ $this->_processPrefixSections($prefix);
+ }
+
+ // 2. apply section ajustments
+ foreach ($prefixes as $prefix) {
+ $config =& $this->Application->UnitConfigReader->configData[$prefix];
+ $section_ajustments = getArrayValue($config, 'SectionAdjustments');
+ if (!$section_ajustments) continue;
+
+ foreach ($section_ajustments as $section_name => $ajustment_params) {
+ if (is_array($ajustment_params)) {
+ if (!array_key_exists($section_name, $this->Tree)) {
+ // don't process ajustments for non-existing sections
+ continue;
+ }
+
+ $this->Tree[$section_name] = array_merge_recursive2($this->Tree[$section_name], $ajustment_params);
+ }
+ else {
+ // then remove section
+ unset($this->Tree[$section_name]);
+ }
+ }
+ }
+
+ // 3.
+ foreach ($this->Tree as $section_name => $section_params) {
+ // 3.1. update parent -> children references
+ $parent_section = $section_params['parent'];
+ $section_order = "{$section_params['priority']}";
+
+ if (!isset($parent_section)) {
+ // don't process parent section of "in-portal:root" section
+ continue;
+ }
+
+ if (!array_key_exists('children', $this->Tree[$parent_section])) {
+ $this->Tree[$parent_section]['children'] = Array ();
+ }
+
+ if (array_key_exists($section_order, $this->Tree[$parent_section]['children'])) {
+ trigger_error(
+ 'Section "<strong>' . $section_name . '</strong>" has replaced section "<strong>' .
+ $this->Tree[$parent_section]['children'][$section_order] .
+ '</strong>" (parent section: "<strong>' . $parent_section .
+ '</strong>"; duplicate priority: <strong>' . $section_order . '</strong>)',
+ E_USER_WARNING
+ );
+ }
+
+ $this->Tree[$parent_section]['children'][$section_order] = $section_name;
+
+ if ($section_params['type'] == stTAB) {
+ // if this is tab, then mark parent section as TabOnly
+ $this->Tree[$parent_section]['tabs_only'] = true;
+ }
+
+ // 3.2. process icons here, because they also can be ajusted
+ if (isset($section_params['icon']) && preg_match('/([^:]+):(.*)/', $section_params['icon'], $regs)) {
+ $this->Tree[$section_name]['icon'] = $regs[2];
+ $this->Tree[$section_name]['icon_module'] = $regs[1]; // set "icon_module" used in "combined_header" block
+ $module_folder = trim( $this->Application->findModule('Name', $regs[1], 'Path'), '/');
+ if ($module_folder == '') {
+ $module_folder = 'core';
+ }
+ }
+ else {
+ $module_folder = $this->Application->getUnitOption($section_params['SectionPrefix'], 'ModuleFolder');
+ if (!array_key_exists('icon_module', $section_params)) {
+ $this->Tree[$section_name]['icon_module'] = $module_folder; // set "icon_module" used in "combined_header" block
+ }
+ }
+
+ // this is to display HELP icon instead of missing one.. can be replaced with some other icon to draw attention
+ $icon_file = $module_folder.'/admin_templates/img/icons/icon24_'.$this->Tree[$section_name]['icon'];
+
+ /*$core_file = FULL_PATH.'/core/admin_templates/img/icons/icon24_' . $this->Tree[$section_name]['icon'].'.gif';
+ if ($module_folder != 'core' && file_exists($core_file) && file_exists(FULL_PATH.'/'.$icon_file.'.gif')) {
+ if (crc32(file_get_contents($core_file)) == crc32(file_get_contents(FULL_PATH.'/'.$icon_file.'.gif'))) {
+ trigger_error('Section "<strong>' . $section_name . '</strong>" uses icon copy from "Core" module', E_USER_NOTICE);
+ }
+ }*/
+
+ if (!file_exists(FULL_PATH.'/'.$icon_file.'.gif')) {
+ $this->Tree[$section_name]['icon'] = 'help';
+ $this->Tree[$section_name]['icon_module'] = 'core';
+ }
+ }
+ $this->Application->HandleEvent( new kEvent('adm:OnAfterBuildTree') );
+
+ if (isset($this->Application->Memcached)) {
+ $this->Application->Memcached->set('master:sections_parsed',serialize($this->Tree), 0, 0);
+ return;
+ }
+
+ $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("sections_parsed", '.$this->Conn->qstr(serialize($this->Tree)).', '.adodb_mktime().')');
+ }
+
+ function _processPrefixSections($prefix)
+ {
+ $config =& $this->Application->UnitConfigReader->configData[$prefix];
+ $sections = getArrayValue($config, 'Sections');
+ if (!$sections) {
+ return ;
+ }
+
+// echo 'Prefix: ['.$prefix.'] has ['.count($sections).'] sections<br />';
+
+ foreach ($sections as $section_name => $section_params) {
+ // we could also skip not allowed sections here in future
+ if ( isset($section_params['SectionPrefix']) ) {
+ $section_prefix = $section_params['SectionPrefix'];
+ }
+ elseif ( $this->Application->getUnitOption($prefix, 'SectionPrefix') ) {
+ $section_prefix = $this->Application->getUnitOption($prefix, 'SectionPrefix');
+ }
+ else {
+ $section_prefix = $prefix;
+ }
+ $section_params['SectionPrefix'] = $section_prefix;
+ $section_params['url']['m_opener'] = 'r';
+ $section_params['url']['no_pass_through'] = 1;
+ $pass_section = getArrayValue($section_params, 'url', 'pass_section');
+
+ if ($pass_section) {
+ unset($section_params['url']['pass_section']);
+ $section_params['url']['section'] = $section_name;
+ if (!isset($section_params['url']['module'])) {
+ $module_name = $this->Application->findModule('Path', $config['ModuleFolder'].'/', 'Name');
+ $section_params['url']['module'] = $module_name;
+ }
+ }
+
+ if (!isset($section_params['url']['t'])) {
+ $section_params['url']['t'] = 'index';
+ }
+
+ if (!isset($section_params['onclick'])) {
+ $section_params['onclick'] = 'checkEditMode()';
+ }
+
+ if (!isset($section_params['container'])) {
+ $section_params['container'] = 0; // for js tree printing to xml
+ }
+
+ $current_data = isset($this->Tree[$section_name]) ? $this->Tree[$section_name] : Array();
+
+ if ($current_data) {
+ trigger_error('Section "<strong>' . $section_name . '</strong>" declaration (originally defined in "<strong>' . $current_data['SectionPrefix'] . '</strong>") was overwriten from "<strong>' . $prefix . '</strong>"', E_USER_NOTICE);
+ }
+
+ $this->Tree[$section_name] = array_merge_recursive2($current_data, $section_params);
+ }
+ }
+
+ /**
+ * Returns details information about section
+ *
+ * @param string $section_name
+ * @return Array
+ */
+ function &getSectionData($section_name)
+ {
+ if (isset($this->Tree[$section_name])) {
+ $ret =& $this->Tree[$section_name];
+ }
+ else {
+ $ret = Array();
+ }
+ return $ret;
+ }
+
+ /**
+ * Returns first child, that is not a folder
+ *
+ * @param string $section_name
+ * @param Array $tree
+ * @return stirng
+ */
+ function getFirstChild($section_name, $check_permission = false)
+ {
+ $section_data =& $this->getSectionData($section_name);
+
+ $children = isset($section_data['children']) && $section_data['children'] ? $section_data['children'] : false;
+ if ($children) {
+ // get 1st child
+ ksort($children, SORT_NUMERIC);
+ foreach ($children as $child_priority => $child_section) {
+ $section_data =& $this->getSectionData($child_section);
+
+ $perm_section = $this->getPermSection($child_section);
+ $perm_status = $check_permission ? $this->Application->CheckPermission($perm_section.'.view') : true;
+ if ((isset($section_data['show_mode']) && $section_data['show_mode']) || !$perm_status) {
+ continue;
+ }
+
+ break;
+ }
+
+ return $this->getFirstChild($child_section, $check_permission);
+ }
+
+ return $section_name;
+ }
+
+ /**
+ * Returns section for permission checking based on given section
+ *
+ * @param string $section_name
+ * @return string
+ */
+ function getPermSection($section_name)
+ {
+ $ret = $section_name;
+ $section_data =& $this->getSectionData($section_name);
+
+ if ($section_data && isset($section_data['perm_prefix'])) {
+ // this section uses other section permissions
+ $ret = $this->Application->getUnitOption($section_data['perm_prefix'].'.main', 'PermSection');
+ }
+ return $ret;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/sections_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.12.2.11
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/helpers_config.php
===================================================================
--- branches/5.0.x/core/units/helpers/helpers_config.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/helpers_config.php (revision 12306)
@@ -0,0 +1,58 @@
+<?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.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+ $config = Array (
+
+ 'Prefix' => 'helpers',
+ 'EventHandlerClass' => Array ('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'),
+
+ 'RegisterClasses' => Array (
+ Array ('pseudo' => 'kMultiLanguageHelper', 'class' => 'kMultiLanguageHelper', 'file' => 'multilanguage.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'SearchHelper', 'class' => 'kSearchHelper', 'file' => 'search_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'SectionsHelper', 'class' => 'kSectionsHelper', 'file' => 'sections_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'PermissionsHelper', 'class' => 'kPermissionsHelper', 'file' => 'permissions_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'ModulesHelper', 'class' => 'kModulesHelper', 'file' => 'modules.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'ModRewriteHelper', 'class' => 'kModRewriteHelper', 'file' => 'mod_rewrite_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'RecursiveHelper', 'class' => 'kRecursiveHelper', 'file' => 'recursive_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'FilenamesHelper', 'class' => 'kFilenamesHelper', 'file' => 'filenames_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'ClipboardHelper', 'class' => 'kClipboardHelper', 'file' => 'clipboard_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'ColumnPickerHelper', 'class' => 'kColumnPickerHelper', 'file' => 'col_picker_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'ThemesHelper', 'class' => 'kThemesHelper', 'file' => 'themes_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'CaptchaHelper', 'class' => 'kCaptchaHelper', 'file' => 'captcha_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'PriorityHelper', 'class' => 'kPriorityHelper', 'file' => 'priority_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'CurlHelper', 'class' => 'kCurlHelper', 'file' => 'curl_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'CountHelper', 'class' => 'kCountHelper', 'file' => 'count_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+
+ Array ('pseudo' => 'ImageHelper', 'class' => 'ImageHelper', 'file' => 'image_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'FileHelper', 'class' => 'FileHelper', 'file' => 'file_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'CategoryHelper', 'class' => 'CategoryHelper', 'file' => 'category_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'CSVHelper', 'class' => 'kCSVHelper', 'file' => 'csv_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'ChartHelper', 'class' => 'kChartHelper', 'file' => 'chart_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'RatingHelper', 'class' => 'RatingHelper', 'file' => 'rating_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'FCKHelper', 'class' => 'fckFCKHelper', 'file' => 'fck_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'SpamHelper', 'class' => 'SpamHelper', 'file' => 'spam_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'TemplateHelper', 'class' => 'TemplateHelper', 'file' => 'template_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'MailingListHelper', 'class' => 'MailingListHelper', 'file' => 'mailing_list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'JSONHelper', 'class' => 'JSONHelper', 'file' => 'json_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'LanguageImportHelper', 'class' => 'LanguageImportHelper', 'file' => 'language_import_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'SkinHelper', 'class' => 'SkinHelper', 'file' => 'skin_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+
+ Array ('class' => 'InpCustomFieldsHelper', 'pseudo' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('class' => 'kCountryStatesHelper', 'pseudo' => 'CountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('class' => 'kBracketsHelper', 'pseudo' => 'BracketsHelper', 'file' => 'brackets_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('class' => 'kXMLHelper', 'pseudo' => 'kXMLHelper', 'file' => 'xml_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ ),
+ );
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/helpers_config.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.9.2.10
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/template_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/template_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/template_helper.php (revision 12306)
@@ -0,0 +1,448 @@
+<?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 TemplateHelper extends kHelper {
+
+ /**
+ * parser element location information
+ *
+ * @var Array
+ */
+ var $_blockLocation = Array ();
+
+ /**
+ * Block name, that will be used
+ *
+ * @var string
+ */
+ var $_blockName = '';
+
+ /**
+ * Function name, that represents compiled block
+ *
+ * @var sting
+ */
+ var $_functionName = '';
+
+ /**
+ * Errors found during template parsing
+ *
+ * @var Array
+ */
+ var $_parseErrors = Array ();
+
+ /**
+ * Source template, that is being edited
+ *
+ * @var string
+ */
+ var $_sourceTemplate = '';
+
+ var $_initMade = false;
+
+ /**
+ * Performs init ot helper
+ *
+ * @param kDBItem $object
+ */
+ function InitHelper(&$object)
+ {
+ if ($this->_initMade) {
+ return ;
+ }
+
+ define('DBG_IGNORE_FATAL_ERRORS', 1);
+
+ // 1. get block information
+ $block_info = $this->Application->GetVar('block');
+ list ($this->_blockName, $this->_functionName) = explode(':', $block_info);
+
+ $this->_parseTemplate($object);
+
+ if (array_key_exists($this->_functionName, $this->Application->Parser->ElementLocations)) {
+ $this->_blockLocation = $this->Application->Parser->ElementLocations[$this->_functionName];
+ }
+
+ $this->_initMade = true;
+ }
+
+ function _getSourceTemplate()
+ {
+ // get source template
+ $t = $this->Application->GetVar('source');
+
+ if (!$this->Application->TemplatesCache->TemplateExists($t)) {
+ $cms_handler =& $this->Application->recallObject('st_EventHandler');
+ /* @var $cms_handler StructureEventHandler */
+
+ $t = ltrim($cms_handler->GetDesignTemplate($t), '/');
+ }
+
+ $this->_sourceTemplate = $t;
+ }
+
+ function _getThemeName()
+ {
+ $theme_id = (int)$this->Application->GetVar('theme_id');
+
+ $sql = 'SELECT Name
+ FROM ' . $this->Application->getUnitOption('theme', 'TableName') . '
+ WHERE ' . $this->Application->getUnitOption('theme', 'IDField') . ' = ' . $theme_id;
+ return $this->Conn->GetOne($sql);
+ }
+
+ /**
+ * Render source template to get parse errors OR it's element locations
+ *
+ * @param kDBItem $object
+ * @param string $append
+ * @return bool
+ */
+ function _parseTemplate(&$object, $append = '')
+ {
+ // 1. set internal error handler to catch all parsing errors
+ $error_handlers = $this->Application->errorHandlers;
+ $this->Application->errorHandlers = Array (
+ Array (&$this, '_saveError'),
+ );
+
+ // 2. parse template
+ $this->Application->InitParser( $this->_getThemeName() ); // we have no parser when saving block content
+
+ $this->_getSourceTemplate();
+
+ // design templates have leading "/" in the beginning
+ $this->Application->Parser->Run($this->_sourceTemplate . $append);
+
+ // 3. restore original error handler
+ $this->Application->errorHandlers = $error_handlers;
+
+ if ($this->_parseErrors) {
+ if ($this->_isMainTemplate()) {
+ // 3.1. delete temporary file, that was parsed
+ $filename = $this->_getTemplateFile(false, $append . '.tpl');
+ if (!unlink($filename)) {
+ $error_file = $this->_getTemplateFile(true, $append . '.tpl');
+ $object->SetError('FileContents', 'template_delete_failed', '+Failed to delete temporary template "<strong>' . $error_file . '</strong>"');
+ return false;
+ }
+ }
+ else {
+ // 3.2. restore backup
+ if (!rename($this->_getTemplateFile(false, '.tpl.bak'), $this->_getTemplateFile(false))) {
+ $error_file = $this->_getTemplateFile(true);
+ $object->SetError('FileContents', 'template_restore_failed', '+Failed to restore template "<strong>' . $error_file . '</strong>" from backup.');
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Move elements in template and save changes, when possible
+ *
+ * @param Array $target_order
+ * @return bool
+ */
+ function moveTemplateElements($target_order)
+ {
+ // 2. parse template
+ $this->Application->InitParser(); // we have no parser when saving block content
+
+ $this->_getSourceTemplate();
+
+ $filename = $this->Application->TemplatesCache->GetRealFilename($this->_sourceTemplate) . '.tpl';
+ if (!is_writable($filename)) {
+ // we can't save changes, don't bother calculating new template contents
+ return false;
+ }
+
+ $data = file_get_contents($filename);
+
+ $line_ending = strpos($data, "\r") !== false ? "\r\n" : "\n";
+
+ // 1. get location of movable areas
+ $mask = '';
+ $start_pos = 0;
+ $elements = Array ();
+ $areas = $this->_getDivPairs($data, 'movable-area');
+ foreach ($areas as $area_index => $area) {
+ // 1.1. get locations of all movable elements inside given area
+ $area_content = substr($area['data'], $area['open_len'], -$area['close_len']);
+ $elements = array_merge($elements, $this->_getDivPairs($area_content, 'movable-element', $area_index, $area['open_pos'] + $area['open_len']));
+
+ // 1.2. prepare mask to place movable elements into (don't include movable area div ifself)
+ $mask .= "\t" . substr($data, $start_pos, $area['open_pos'] + $area['open_len'] - $start_pos) . $line_ending . "\t\t" . '#AREA' . $area_index . '#' . $line_ending;
+ $start_pos = $area['close_pos'] - $area['close_len'];
+ }
+ $mask = trim($mask . "\t" . substr($data, $area['close_pos'] - $area['close_len']));
+
+ if (!$elements) {
+ // no elements found
+ return false;
+ }
+
+ foreach ($areas as $area_index => $area) {
+ $area_content = '';
+ $target_elements = $target_order[$area_index];
+ foreach ($target_order[$area_index] as $old_location) {
+ $area_content .= $elements[$old_location]['data'] . $line_ending . "\t\t";
+ }
+
+ $mask = str_replace('#AREA' . $area_index . '#', trim($area_content), $mask);
+ }
+
+ $fp = fopen($filename, 'w');
+ fwrite($fp, $mask);
+ fclose($fp);
+
+ return true;
+ }
+
+ /**
+ * Extracts div pairs with given class from given text
+ *
+ * @param string $data
+ * @param string $class
+ * @param int $area
+ * @param int $offset
+ * @return Array
+ */
+ function _getDivPairs(&$data, $class, $area = null, $offset = 0)
+ {
+ preg_match_all('/(<div[^>]*>)|(<\/div>)/s', $data, $divs, PREG_SET_ORDER + PREG_OFFSET_CAPTURE);
+
+ $skip_count = 0;
+ $pairs = Array ();
+
+ foreach ($divs as $div) {
+ if (strpos($div[0][0], '/') === false) {
+ // opening div
+ if (strpos($div[0][0], $class) !== false) {
+ $pair = Array ('open_pos' => $div[0][1], 'open_len' => strlen($div[0][0]));
+ $skip_count = 0;
+ }
+ else {
+ $skip_count++;
+ }
+ }
+ else {
+ // closing div
+ if ($skip_count == 0) {
+ $pair['close_len'] = strlen($div[0][0]);
+ $pair['close_pos'] = $div[0][1] + $pair['close_len'];
+ $pair['data'] = substr($data, $pair['open_pos'], $pair['close_pos'] - $pair['open_pos']);
+
+ if (isset($area)) {
+ $pair['open_pos'] += $offset;
+ $pair['close_pos'] += $offset;
+ // index indicates area
+ $pairs['a' . $area . 'e' . count($pairs)] = $pair;
+ }
+ else {
+ $pairs[] = $pair;
+ }
+ }
+ else {
+ $skip_count--;
+ }
+ }
+ }
+
+ return $pairs;
+ }
+
+ /**
+ * Returns information about parser element locations in template
+ *
+ * @param Array $params
+ * @return mixed
+ */
+ function blockInfo($info_type)
+ {
+ switch ($info_type) {
+ case 'block_name':
+ return $this->_blockName;
+ break;
+
+ case 'function_name':
+ return $this->_functionName;
+ break;
+
+ case 'start_pos':
+ case 'end_pos':
+ case 'template':
+ if (!array_key_exists($info_type, $this->_blockLocation)) {
+ // invalid block name
+ return 'invalid block name';
+ }
+
+ return $this->_blockLocation[$info_type];
+ break;
+
+ case 'template_file':
+ return $this->_getTemplateFile(true);
+ break;
+
+ case 'content':
+ $template_body = file_get_contents( $this->_getTemplateFile() );
+ $length = $this->_blockLocation['end_pos'] - $this->_blockLocation['start_pos'];
+
+ return substr($template_body, $this->_blockLocation['start_pos'], $length);
+ break;
+ }
+
+ return 'undefined';
+ }
+
+ /**
+ * Main template being edited (parse copy, instead of original)
+ *
+ * @return bool
+ */
+ function _isMainTemplate()
+ {
+ return $this->_blockLocation['template'] == $this->_sourceTemplate;
+ }
+
+ /**
+ * Returns filename, that contains template, where block is located
+ *
+ * @return string
+ */
+ function _getTemplateFile($relative = false, $extension = '.tpl')
+ {
+ $filename = $this->Application->TemplatesCache->GetRealFilename( $this->_blockLocation['template'] ) . $extension;
+
+ if ($relative) {
+ $filename = preg_replace('/^' . preg_quote(FULL_PATH, '/') . '/', '', $filename, 1);
+ }
+
+ return $filename;
+ }
+
+ /**
+ * Saves new version of block to template, where it's located
+ *
+ * @param kDBItem $object
+ */
+ function saveBlock(&$object)
+ {
+ $main_template = $this->_isMainTemplate();
+ $filename = $this->_getTemplateFile(false);
+
+ // 1. get new template content
+ $new_template_body = $this->_getNewTemplateContent($object, $filename, $lines_before);
+ if (is_bool($new_template_body) && ($new_template_body === true)) {
+ // when nothing changed -> stop processing
+ return true;
+ }
+
+ // 2. backup original template
+ if (!$main_template && !copy($filename, $filename . '.bak')) {
+ // backup failed
+ $error_file = $this->_getTemplateFile(true, '.tpl.bak');
+ $object->SetError('FileContents', 'template_backup_failed', '+Failed to create backup template "<strong>' . $error_file . '</strong>" backup.');
+ return false;
+ }
+
+ // 3. save changed template
+ $save_filename = $this->_getTemplateFile(false, $main_template ? '.tmp.tpl' : '.tpl');
+ $fp = fopen($save_filename, 'w');
+ if (!$fp) {
+ // backup template create failed OR existing template save
+ $error_file = $this->_getTemplateFile(true, $main_template ? '.tmp.tpl' : '.tpl');
+ $object->SetError('FileContents', 'template_changes_save_failed', '+Failed to save template "<strong>' . $error_file . '</strong>" changes.');
+ return false;
+ }
+ fwrite($fp, $new_template_body);
+ fclose($fp);
+
+ // 3. parse template to check for errors
+ $this->_parseTemplate($object, $main_template ? '.tmp' : '');
+
+ if ($this->_parseErrors) {
+ $error_msg = Array ();
+ foreach ($this->_parseErrors as $error_data) {
+ if (preg_match('/line ([\d]+)/', $error_data['msg'], $regs)) {
+ // another line number inside message -> patch it
+ $error_data['msg'] = str_replace('line ' . $regs[1], 'line ' . ($regs[1] - $lines_before), $error_data['msg']);
+ }
+
+ $error_msg[] = $error_data['msg'] . ' at line ' . ($error_data['line'] - $lines_before);
+ }
+
+ $object->SetError('FileContents', 'template_syntax_error', '+Template syntax errors:<br/>' . implode('<br/>', $error_msg));
+ return false;
+ }
+
+ if ($main_template) {
+ // 4.1. replace original file with temporary
+ if (!rename($this->_getTemplateFile(false, '.tmp.tpl'), $filename)) {
+ // failed to save new content to original template
+ $error_file = $this->_getTemplateFile(true);
+ $object->SetError('FileContents', 'template_save_failed', '+Failed to save template "<strong>' . $error_file . '</strong>".');
+ return false;
+ }
+ }
+ else {
+ // 4.2. delete backup
+ unlink( $this->_getTemplateFile(false, '.tpl.bak') );
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns new template content of "true", when nothing is changed
+ *
+ * @param kDBItem $object
+ * @param string $filename
+ * @param int $lines_before
+ * @return mixed
+ */
+ function _getNewTemplateContent(&$object, $filename, &$lines_before)
+ {
+ $new_content = $object->GetDBField('FileContents');
+
+ $template_body = file_get_contents($filename);
+ $lines_before = substr_count(substr($template_body, 0, $this->_blockLocation['start_pos']), "\n");
+
+ $new_template_body = substr($template_body, 0, $this->_blockLocation['start_pos']) .
+ $new_content .
+ substr($template_body, $this->_blockLocation['end_pos']);
+
+ return crc32($template_body) == crc32($new_template_body) ? true : $new_template_body;
+ }
+
+ function _saveError($errno, $errstr, $errfile, $errline, $errcontext)
+ {
+ if ($errno != E_USER_ERROR) {
+ // ignore all minor errors, except fatals from parser
+ return true;
+ }
+
+ /*if (defined('E_STRICT') && ($errno == E_STRICT)) {
+ // always ignore strict errors here (specially when not in debug mode)
+ return true;
+ }*/
+
+ $this->_parseErrors[] = Array ('msg' => $errstr, 'file' => $errfile, 'line' => $errline);
+ return true;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/template_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.1.2.5
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property

Event Timeline