Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Sat, Feb 22, 12:04 AM

in-portal

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: branches/5.3.x/admin/system_presets/simple/inp_ckconfig.js
===================================================================
--- branches/5.3.x/admin/system_presets/simple/inp_ckconfig.js (revision 15945)
+++ branches/5.3.x/admin/system_presets/simple/inp_ckconfig.js (revision 15946)
@@ -1,112 +1,131 @@
+CKEDITOR.config.title = '';
+
/*
* Append here extra CSS rules that should be applied into the editing area.
* Example:
* config.extraCss = "body {color:#FF0000;}";
*/
CKEDITOR.config.extraCss = "";
/**
* CKEditor's editing area body ID & class.
* This setting can be used if CKEditor does not work well with your theme by default.
*/
CKEDITOR.config.bodyClass = '';
CKEDITOR.config.bodyId = '';
// Preview
//CKEDITOR.config.PreviewUrl = '';
//CKEDITOR.config.ContentId = '';
//CKEDITOR.config.PreloadImages = [ CKEDITOR.config.SkinPath + 'images/toolbar.start.gif', CKEDITOR.config.SkinPath + 'images/toolbar.buttonarrow.gif', CKEDITOR.config.BasePath + 'plugins/images/document.gif' ] ;
//CKEDITOR.config.PluginsPath = CKEDITOR.config.BasePath + 'plugins/' ;
CKEDITOR.config.entities = false;
-CKEDITOR.config.extraPlugins = 'my_link,my_document,my_maximize';
+CKEDITOR.config.extraPlugins = 'my_link,my_document,my_maximize,my_inline';
//CKEDITOR.plugins.add('MySource');
//CKEDITOR.plugins.add('MyPreview');
//CKEDITOR.plugins.add('MyLink');
//CKEDITOR.plugins.add('MyImage');
//CKEDITOR.plugins.add('document', 'en,ru');
CKEDITOR.config.protectedSource.push( /(<inp2:[^\>]+>)|(<\/inp2:[^\>]+>)|(<inp2:[^\>]+\/>)/gi ) ;
CKEDITOR.config.documentIconsUrl = '/system/user_files/icons'; // for document custom plugin
CKEDITOR.config.toolbar_Default = [
['Styles'],
['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
['NumberedList', 'BulletedList', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Image', 'Document', 'MediaEmbed', 'Link', '-', 'Undo', 'Redo'],
['Find', 'Replace', 'Scayt']
];
CKEDITOR.config.toolbar_DebugMode = [
['Cut','Copy','Paste','PasteText','PasteFromWord','-','NewPage','SelectAll','-','Find','Replace','-','Print','Preview','-',/*My*/ 'Link','Unlink','Anchor','HorizontalRule','-',/*My*/ 'Image','Flash','MediaEmbed','Document','Table','SpecialChar'],
'/',
['Bold','Italic','Underline','Strike','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','NumberedList','BulletedList','Outdent','Indent','-','Subscript','Superscript','-','TextColor','BGColor','-','Undo','Redo'],
'/',
['Styles','Font','FontSize','RemoveFormat','-','Scayt','-', /*My*/'Source', 'Maximize', 'ShowBlocks']
];
+CKEDITOR.config.toolbar_Inline = [
+ ['InlineSave', 'InlineCancel'],
+ ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Image', 'Document', 'MediaEmbed', 'Link', '-', 'Undo', 'Redo'],
+ ['Find', 'Replace', 'Scayt'],
+ '/',
+ ['Styles'], ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
+ ['NumberedList', 'BulletedList', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock']
+];
+
+/*CKEDITOR.config.toolbar_Simple = [
+ ['Styles'],
+ ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
+ ['NumberedList', 'BulletedList', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
+ ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo'],
+ ['Find', 'Replace', 'Scayt']
+];*/
+
//CKEDITOR.config.toolbar_Full = [
// [ 'Source','-','Save','NewPage','DocProps','Preview','Print','-','Templates' ],
// [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ],
// [ 'Find','Replace','-','SelectAll','-','SpellChecker', 'Scayt' ],
// [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ],
// '/',
// [ 'Bold','Italic','Underline','Strike','Subscript','Superscript','-','RemoveFormat' ],
// [ 'NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote','CreateDiv','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','BidiLtr','BidiRtl' ],
// [ 'Link','Unlink','Anchor' ],
// [ 'Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak' ],
// '/',
// [ 'Styles','Format','Font','FontSize' ],
// [ 'TextColor','BGColor' ],
// [ 'Maximize', 'ShowBlocks','-','About' ]
//];
CKEDITOR.config.enterMode = CKEDITOR.ENTER_BR ; // p | div | br
CKEDITOR.config.shiftEnterMode = CKEDITOR.ENTER_P ; // p | div | br
/*CKEDITOR.config.keystrokes = [
[ CKEDITOR.CTRL + 65 *//*A*//*, true ],
[ CKEDITOR.CTRL + 67 *//*C*//*, true ],
[ CKEDITOR.CTRL + 70 *//*F*//*, true ],
[ CKEDITOR.CTRL + 83 *//*S*//*, true ],
[ CKEDITOR.CTRL + 84 *//*T*//*, true ],
[ CKEDITOR.CTRL + 88 *//*X*//*, true ],
[ CKEDITOR.CTRL + 86 *//*V*//*, 'Paste' ],
[ CKEDITOR.CTRL + 45 *//*INS*//*, true ],
[ CKEDITOR.SHIFT + 45 *//*INS*//*, 'Paste' ],
[ CKEDITOR.CTRL + 88 *//*X*//*, 'Cut' ],
[ CKEDITOR.SHIFT + 46 *//*DEL*//*, 'Cut' ],
[ CKEDITOR.CTRL + 90 *//*Z*//*, 'Undo' ],
[ CKEDITOR.CTRL + 89 *//*Y*//*, 'Redo' ],
[ CKEDITOR.CTRL + CKEDITOR.SHIFT + 90 *//*Z*//*, 'Redo' ],
[ CKEDITOR.CTRL + 76 *//*L*//*, 'Link' ],
[ CKEDITOR.CTRL + 66 *//*B*//*, 'Bold' ],
[ CKEDITOR.CTRL + 73 *//*I*//*, 'Italic' ],
[ CKEDITOR.CTRL + 85 *//*U*//*, 'Underline' ],
[ CKEDITOR.CTRL + CKEDITOR.SHIFT + 83 *//*S*//*, 'Save' ],
[ CKEDITOR.CTRL + CKEDITOR.ALT + 13 *//*ENTER*//*, 'FitWindow' ]
] ;*/
//CKEDITOR.config.menu_groups = 'generic,anchor,flash,select,textarea,checkbox,radio,textfield,hiddenfield,imagebutton,button,bulletedlist,numberedlist,table,form';
CKEDITOR.config.font_names = 'Arial Narrow;Arial;Sans-Serif;Serif;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;
CKEDITOR.config.fontSize_sizes = 'xx-small;x-small;small;medium;large;x-large;xx-large' ;
CKEDITOR.config.filebrowserBrowseUrl = CKEDITOR.basePath + 'ckfinder/ckfinder.html';
CKEDITOR.config.filebrowserUploadUrl = CKEDITOR.basePath + 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files';
CKEDITOR.config.filebrowserImageBrowseUrl = CKEDITOR.basePath + 'ckfinder/ckfinder.html?type=Images';
CKEDITOR.config.filebrowserImageUploadUrl = CKEDITOR.basePath + 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images';
CKEDITOR.config.filebrowserFlashBrowseUrl = CKEDITOR.basePath + 'ckfinder/ckfinder.html?type=Flash';
CKEDITOR.config.filebrowserFlashUploadUrl = CKEDITOR.basePath + 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Flash';
CKEDITOR.config.filebrowserDocumentBrowseUrl = CKEDITOR.basePath + 'ckfinder/ckfinder.html?type=Documents';
// add ability to browse for documents
//CKEDITOR.config.documentsBrowser = true ;
Index: branches/5.3.x/core/kernel/db/db_tag_processor.php
===================================================================
--- branches/5.3.x/core/kernel/db/db_tag_processor.php (revision 15945)
+++ branches/5.3.x/core/kernel/db/db_tag_processor.php (revision 15946)
@@ -1,3188 +1,3050 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kDBTagProcessor extends kTagProcessor {
/**
* Returns true if "new" button was pressed in toolbar
*
* @param Array $params
* @return bool
*/
function IsNewMode($params)
{
$object = $this->getObject($params);
return $object->GetID() <= 0;
}
/**
* Returns view menu name for current prefix
*
* @param Array $params
* @return string
*/
function GetItemName($params)
{
$item_name = $this->getUnitConfig()->getViewMenuPhrase();
return $this->Application->Phrase($item_name);
}
function ViewMenu($params)
{
$block_params = $params;
unset($block_params['block']);
$block_params['name'] = $params['block'];
$list =& $this->GetList($params);
$block_params['PrefixSpecial'] = $list->getPrefixSpecial();
return $this->Application->ParseBlock($block_params);
}
function SearchKeyword($params)
{
$list =& $this->GetList($params);
return $this->Application->RecallVar($list->getPrefixSpecial() . '_search_keyword');
}
/**
* Draw filter menu content (for ViewMenu) based on filters defined in config
*
* @param Array $params
* @return string
*/
function DrawFilterMenu($params)
{
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['spearator_block'];
$separator = $this->Application->ParseBlock($block_params);
$filter_menu = $this->getUnitConfig()->getFilterMenu();
if ( !$filter_menu ) {
trigger_error('<span class="debug_error">no filters defined</span> for prefix <b>' . $this->Prefix . '</b>, but <b>DrawFilterMenu</b> tag used', E_USER_NOTICE);
return '';
}
// Params: label, filter_action, filter_status
$block_params['name'] = $params['item_block'];
$view_filter = $this->Application->RecallVar($this->getPrefixSpecial() . '_view_filter');
if ( $view_filter === false ) {
$event_params = Array ('prefix' => $this->Prefix, 'special' => $this->Special, 'name' => 'OnRemoveFilters');
$this->Application->HandleEvent(new kEvent($event_params));
$view_filter = $this->Application->RecallVar($this->getPrefixSpecial() . '_view_filter');
}
$view_filter = unserialize($view_filter);
$filters = Array ();
$prefix_special = $this->getPrefixSpecial();
foreach ($filter_menu['Filters'] as $filter_key => $filter_params) {
$group_params = isset($filter_params['group_id']) ? $filter_menu['Groups'][$filter_params['group_id']] : Array ();
if ( !isset($group_params['element_type']) ) {
$group_params['element_type'] = 'checkbox';
}
if ( !$filter_params ) {
$filters[] = $separator;
continue;
}
$block_params['label'] = $filter_params['label'];
if ( getArrayValue($view_filter, $filter_key) ) {
$submit = 0;
if ( isset($params['old_style']) ) {
$status = $group_params['element_type'] == 'checkbox' ? 1 : 2;
}
else {
$status = $group_params['element_type'] == 'checkbox' ? '[\'img/check_on.gif\']' : '[\'img/menu_dot.gif\']';
}
}
else {
$submit = 1;
$status = 'null';
}
$block_params['filter_action'] = 'set_filter("' . $prefix_special . '","' . $filter_key . '","' . $submit . '",' . $params['ajax'] . ');';
$block_params['filter_status'] = $status; // 1 - checkbox, 2 - radio, 0 - no image
$filters[] = $this->Application->ParseBlock($block_params);
}
return implode('', $filters);
}
/**
* Draws auto-refresh submenu in View Menu.
*
* @param Array $params
* @return string
*/
function DrawAutoRefreshMenu($params)
{
$refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals');
if (!$refresh_intervals) {
trigger_error('<span class="debug_error">no refresh intervals defined</span> for prefix <strong>'.$this->Prefix.'</strong>, but <strong>DrawAutoRefreshMenu</strong> tag used', E_USER_NOTICE);
return '';
}
$refresh_intervals = explode(',', $refresh_intervals);
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
$current_refresh_interval = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name);
if ($current_refresh_interval === false) {
// if no interval was selected before, then choose 1st interval
$current_refresh_interval = $refresh_intervals[0];
}
$ret = '';
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
foreach ($refresh_intervals as $refresh_interval) {
$block_params['label'] = $this->_formatInterval($refresh_interval);
$block_params['refresh_interval'] = $refresh_interval;
$block_params['selected'] = $current_refresh_interval == $refresh_interval;
$ret .= $this->Application->ParseBlock($block_params);
}
return $ret;
}
/**
* Tells, that current grid is using auto refresh
*
* @param Array $params
* @return bool
*/
function UseAutoRefresh($params)
{
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_auto_refresh.'.$view_name);
}
/**
* Returns current grid refresh interval
*
* @param Array $params
* @return bool
*/
function AutoRefreshInterval($params)
{
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name);
}
/**
* Formats time interval using given text for hours and minutes
*
* @param int $interval minutes
* @param string $hour_text Text for hours
* @param string $min_text Text for minutes
* @return string
*/
function _formatInterval($interval, $hour_text = 'h', $min_text = 'min')
{
// 65
$minutes = $interval % 60;
$hours = ($interval - $minutes) / 60;
$ret = '';
if ($hours) {
$ret .= $hours.$hour_text.' ';
}
if ($minutes) {
$ret .= $minutes.$min_text;
}
return $ret;
}
function IterateGridFields($params)
{
$mode = $params['mode'];
$def_block = isset($params['block']) ? $params['block'] : '';
$force_block = isset($params['force_block']) ? $params['force_block'] : false;
$grid = $this->getUnitConfig()->getGridByName($params['grid']);
$grid_config = $grid['Fields'];
$picker_helper = new kColumnPickerHelper($this->getPrefixSpecial(), $params['grid']);
$grid_config = $picker_helper->apply($grid_config);
if ( $mode == 'fields' ) {
return "'" . join("','", array_keys($grid_config)) . "'";
}
$object =& $this->GetList($params);
$o = '';
$i = 0;
foreach ($grid_config as $field => $options) {
$i++;
$block_params = $this->prepareTagParams($params);
$block_params = array_merge($block_params, $options);
$block_params['block_name'] = array_key_exists($mode . '_block', $block_params) ? $block_params[$mode . '_block'] : $def_block;
$block_params['name'] = $force_block ? $force_block : $block_params['block_name'];
$block_params['field'] = $field;
$block_params['sort_field'] = isset($options['sort_field']) ? $options['sort_field'] : $field;
$block_params['filter_field'] = isset($options['filter_field']) ? $options['filter_field'] : $field;
$w = $picker_helper->getWidth($field);
if ( $w ) {
// column picker width overrides width from unit config
$block_params['width'] = $w;
}
$field_options = $object->GetFieldOptions($field);
if ( array_key_exists('use_phrases', $field_options) ) {
$block_params['use_phrases'] = $field_options['use_phrases'];
}
$block_params['is_last'] = ($i == count($grid_config));
$o .= $this->Application->ParseBlock($block_params, 1);
}
return $o;
}
function PickerCRC($params)
{
$picker_helper = new kColumnPickerHelper($this->getPrefixSpecial(), $params['grid']);
return $picker_helper->getData()->getChecksum();
}
function FreezerPosition($params)
{
$picker_helper = new kColumnPickerHelper($this->getPrefixSpecial(), $params['grid']);
$data = $picker_helper->getData();
$freezer_pos = $data->getOrder('__FREEZER__');
return $freezer_pos === false || $data->isHidden('__FREEZER__') ? 1 : ++$freezer_pos;
}
function GridFieldsCount($params)
{
$grid = $this->getUnitConfig()->getGridByName($params['grid']);
return count($grid['Fields']);
}
/**
* Prints list content using block specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintList($params)
{
$params['no_table'] = 1;
return $this->PrintList2($params);
}
function InitList($params)
{
$list_name = isset($params['list_name']) ? $params['list_name'] : '';
$names_mapping = $this->Application->GetVar('NamesToSpecialMapping', Array ());
if ( getArrayValue($names_mapping, $this->Prefix, $list_name) === false ) {
$list =& $this->GetList($params);
}
}
function BuildListSpecial($params)
{
return $this->Special;
}
/**
* Returns key, that identifies each list on template (used internally, not tag)
*
* @param Array $params
* @return string
*/
function getUniqueListKey($params)
{
$types = array_key_exists('types', $params) ? $params['types'] : '';
$except = array_key_exists('except', $params) ? $params['except'] : '';
$list_name = array_key_exists('list_name', $params) ? $params['list_name'] : '';
if (!$list_name) {
$list_name = $this->Application->Parser->GetParam('list_name');
}
return $types . $except . $list_name;
}
/**
* Enter description here...
*
* @param Array $params
* @return kDBList
*/
function &GetList($params)
{
$list_name = $this->SelectParam($params, 'list_name,name');
if ( !$list_name ) {
$list_name = $this->Application->Parser->GetParam('list_name');
}
$requery = isset($params['requery']) && $params['requery'];
$main_list = array_key_exists('main_list', $params) && $params['main_list'];
$names_mapping = $this->Application->GetVar('NamesToSpecialMapping', Array ());
if ( !array_key_exists($this->Prefix, $names_mapping) ) {
// create prefix-based array to special mapping storage
$names_mapping[$this->Prefix] = Array ();
}
if ( $list_name && !$requery ) {
// list with "list_name" parameter
if ( !array_key_exists($list_name, $names_mapping[$this->Prefix]) ) {
// special missing -> generate one
$special = $main_list ? $this->Special : $this->BuildListSpecial($params);
}
else {
// get special, formed during list initialization
$special = $names_mapping[$this->Prefix][$list_name];
}
}
else {
// list without "list_name" parameter
$special = $main_list ? $this->Special : $this->BuildListSpecial($params);
}
$prefix_special = rtrim($this->Prefix . '.' . $special, '.');
$params['skip_counting'] = true;
$list = $this->Application->recallObject($prefix_special, $this->Prefix . '_List', $params);
/* @var $list kDBList */
if ( !array_key_exists('skip_quering', $params) || !$params['skip_quering'] ) {
if ( $requery ) {
$this->Application->HandleEvent(new kEvent($prefix_special . ':OnListBuild', $params));
}
if ( array_key_exists('offset', $params) ) {
$list->SetOffset($list->GetOffset() + $params['offset']); // apply custom offset
}
$list->Query($requery);
if ( array_key_exists('offset', $params) ) {
$list->SetOffset($list->GetOffset() - $params['offset']); // remove custom offset
}
}
$this->Init($this->Prefix, $special);
if ( $list_name ) {
$names_mapping[$this->Prefix][$list_name] = $special;
$this->Application->SetVar('NamesToSpecialMapping', $names_mapping);
}
return $list;
}
function ListMarker($params)
{
$list =& $this->GetList($params);
$ret = $list->getPrefixSpecial();
if (array_key_exists('as_preg', $params) && $params['as_preg']) {
$ret = preg_quote($ret, '/');
}
return $ret;
}
function CombinedSortingDropDownName($params)
{
$list =& $this->GetList($params);
return $list->getPrefixSpecial() . '_CombinedSorting';
}
/**
* Prepares name for field with event in it (used only on front-end)
*
* @param Array $params
* @return string
*/
function SubmitName($params)
{
$list =& $this->GetList($params);
$prefix_special = $list->getPrefixSpecial();
return 'events[' . $prefix_special . '][' . $params['event'] . ']';
}
/**
* Prints list content using block specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintList2($params)
{
$per_page = $this->SelectParam($params, 'per_page,max_items');
if ( $per_page !== false ) {
$params['per_page'] = $per_page;
}
$list =& $this->GetList($params);
$o = '';
$direction = (isset($params['direction']) && $params['direction'] == "H") ? "H" : "V";
$columns = (isset($params['columns'])) ? $params['columns'] : 1;
$config = $this->getUnitConfig();
$id_field = (isset($params['id_field'])) ? $params['id_field'] : $config->getIDField();
if ( $columns > 1 && $direction == 'V' ) {
$records_left = array_splice($list->Records, $list->GetSelectedCount()); // because we have 1 more record for "More..." link detection (don't need to sort it)
$list->Records = $this->LinearToVertical($list->Records, $columns, $list->GetPerPage());
$list->Records = array_merge($list->Records, $records_left);
}
$list->GoFirst();
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
$block_params['pass_params'] = 'true';
$block_params['column_width'] = $params['column_width'] = 100 / $columns;
$block_start_row_params = $this->prepareTagParams($params);
$block_start_row_params['name'] = $this->SelectParam($params, 'row_start_render_as,block_row_start,row_start_block');
$block_end_row_params = $this->prepareTagParams($params);
$block_end_row_params['name'] = $this->SelectParam($params, 'row_end_render_as,block_row_end,row_end_block');
$block_empty_cell_params = $this->prepareTagParams($params);
$block_empty_cell_params['name'] = $this->SelectParam($params, 'empty_cell_render_as,block_empty_cell,empty_cell_block');
$i = 0;
$backup_id = $this->Application->GetVar($this->Prefix . '_id');
$displayed = Array ();
$column_number = 1;
$cache_mod_rw = $config->getCacheModRewrite() && $this->Application->RewriteURLs() && !$this->Application->isCachingType(CACHING_TYPE_MEMORY);
$limit = isset($params['limit']) ? $params['limit'] : false;
while (!$list->EOL() && (!$limit || $i<$limit)) {
$this->Application->SetVar($this->getPrefixSpecial() . '_id', $list->GetDBField($id_field)); // for edit/delete links using GET
$this->Application->SetVar($this->Prefix . '_id', $list->GetDBField($id_field));
$block_params['is_last'] = ($i == $list->GetSelectedCount() - 1);
$block_params['last_row'] = ($i + (($i + 1) % $columns) >= $list->GetSelectedCount() - 1);
$block_params['not_last'] = !$block_params['is_last']; // for front-end
if ( $cache_mod_rw ) {
$serial_name = $this->Application->incrementCacheSerial($this->Prefix, $list->GetDBField($id_field), false);
if ( $this->Prefix == 'c' ) {
// for listing subcategories in category
$this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('NamedParentPath'));
$this->Application->setCache('category_tree[%CIDSerial:' . $list->GetDBField($id_field) . '%]', $list->GetDBField('TreeLeft') . ';' . $list->GetDBField('TreeRight'));
}
else {
// for listing items in category
$this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('Filename'));
$serial_name = $this->Application->incrementCacheSerial('c', $list->GetDBField('CategoryId'), false);
$this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('CategoryFilename'));
}
}
if ( $i % $columns == 0 ) {
// record in this iteration is first in row, then open row
$column_number = 1;
$o .= $block_start_row_params['name'] ? $this->Application->ParseBlock($block_start_row_params) : (!isset($params['no_table']) ? '<tr>' : '');
}
else {
$column_number++;
}
$block_params['first_col'] = $column_number == 1 ? 1 : 0;
$block_params['last_col'] = $column_number == $columns ? 1 : 0;
$block_params['column_number'] = $column_number;
$block_params['num'] = ($i + 1);
$this->PrepareListElementParams($list, $block_params); // new, no need to rewrite PrintList
$o .= $this->Application->ParseBlock($block_params);
array_push($displayed, $list->GetDBField($id_field));
if ( $direction == 'V' && $list->GetSelectedCount() % $columns > 0 && $column_number == ($columns - 1) && ceil(($i + 1) / $columns) > $list->GetSelectedCount() % ceil($list->GetSelectedCount() / $columns) ) {
// if vertical output, then draw empty cells vertically, not horizontally
$o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params) : '<td>&nbsp;</td>';
$i++;
}
if ( ($i + 1) % $columns == 0 ) {
// record in next iteration is first in row too, then close this row
$o .= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params) : (!isset($params['no_table']) ? '</tr>' : '');
}
if ( $this->Special && $this->Application->hasObject($this->Prefix) ) {
// object, produced by "kDBList::linkToParent" method, that otherwise would keep it's id
$item = $this->Application->recallObject($this->Prefix);
/* @var $item kDBBase */
if ( $item instanceof kDBItem ) {
$this->Application->removeObject($this->Prefix);
}
}
$list->GoNext();
$i++;
}
// append empty cells in place of missing cells in last row
while ($i % $columns != 0) {
// until next cell will be in new row append empty cells
$o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params) : '<td>&nbsp;</td>';
if ( ($i + 1) % $columns == 0 ) {
// record in next iteration is first in row too, then close this row
$o .= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params) : '</tr>';
}
$i++;
}
$cur_displayed = $this->Application->GetVar($this->Prefix . '_displayed_ids');
if ( !$cur_displayed ) {
$cur_displayed = Array ();
}
else {
$cur_displayed = explode(',', $cur_displayed);
}
$displayed = array_unique(array_merge($displayed, $cur_displayed));
$this->Application->SetVar($this->Prefix . '_displayed_ids', implode(',', $displayed));
$this->Application->SetVar($this->Prefix . '_id', $backup_id);
$this->Application->SetVar($this->getPrefixSpecial() . '_id', '');
if ( isset($params['more_link_render_as']) ) {
$block_params = $params;
$params['render_as'] = $params['more_link_render_as'];
$o .= $this->MoreLink($params);
}
return $o;
}
/**
* Returns ID of previous record (related to current) in list.
* Use only on item detail pages.
*
* @param Array $params
* @return int
* @access protected
*/
protected function PreviousResource($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$list_helper = $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
$select_clause = $object->getUnitConfig()->getNavigationSelectClause(null);
return $list_helper->getNavigationResource($object, $params['list'], false, $select_clause);
}
/**
* Returns ID of next record (related to current) in list.
* Use only on item detail pages.
*
* @param Array $params
* @return int
* @access protected
*/
protected function NextResource($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$list_helper = $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
$select_clause = $object->getUnitConfig()->getNavigationSelectClause(null);
return $list_helper->getNavigationResource($object, $params['list'], true, $select_clause);
}
/**
* Allows to modify block params & current list record before PrintList parses record
*
* @param kDBList $object
* @param Array $block_params
* @return void
* @access protected
*/
protected function PrepareListElementParams(&$object, &$block_params)
{
// $fields_hash =& $object->getCurrentRecord();
}
/**
* Renders given block name, when there there is more data in list, then are displayed right now
*
* @param Array $params
* @return string
* @access protected
*/
protected function MoreLink($params)
{
$per_page = $this->SelectParam($params, 'per_page,max_items');
if ( $per_page !== false ) {
$params['per_page'] = $per_page;
}
$list =& $this->GetList($params);
if ( $list->isCounted() ) {
$has_next_page = $list->GetPage() < $list->GetTotalPages();
}
else {
// selected more, then on the page -> has more
$has_next_page = $list->GetPerPage() < $list->GetRecordsCount();
}
if ( $has_next_page ) {
$block_params = Array ('name' => $this->SelectParam($params, 'render_as,block'));
return $this->Application->ParseBlock($block_params);
}
return '';
}
function PageLink($params)
{
static $default_per_page = Array ();
$object =& $this->GetList($params);
/* @var $object kDBList */
// process sorting
if ($object->isMainList()) {
if (!array_key_exists('sort_by', $params)) {
$sort_by = $this->Application->GetVar('sort_by');
if ($sort_by !== false) {
$params['sort_by'] = $sort_by;
}
}
}
$prefix_special = $this->getPrefixSpecial();
// process page
$page = array_key_exists('page', $params) ? $params['page'] : $this->Application->GetVar($prefix_special . '_Page');
if (!$page) {
// ensure, that page is always present
if ($object->isMainList()) {
$params[$prefix_special . '_Page'] = $this->Application->GetVar('page', 1);
}
else {
$params[$prefix_special . '_Page'] = 1;
}
}
if (array_key_exists('page', $params)) {
$params[$prefix_special . '_Page'] = $params['page'];
unset($params['page']);
}
// process per-page
$per_page = array_key_exists('per_page', $params) ? $params['per_page'] : $this->Application->GetVar($prefix_special . '_PerPage');
if (!$per_page) {
// ensure, that per-page is always present
list ($prefix, ) = explode('.', $prefix_special);
if (!array_key_exists($prefix, $default_per_page)) {
$list_helper = $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
$default_per_page[$prefix] = $list_helper->getDefaultPerPage($prefix);
}
if ($object->isMainList()) {
$params[$prefix_special . '_PerPage'] = $this->Application->GetVar('per_page', $default_per_page[$prefix]);
}
else {
$params[$prefix_special . '_PerPage'] = $default_per_page[$prefix];
}
}
if (array_key_exists('per_page', $params)) {
$params[$prefix_special . '_PerPage'] = $params['per_page'];
unset($params['per_page']);
}
if (!array_key_exists('pass', $params)) {
$params['pass'] = 'm,' . $prefix_special;
}
// process template
$t = array_key_exists('template', $params) ? $params['template'] : '';
unset($params['template']);
if (!$t) {
$t = $this->Application->GetVar('t');
}
return $this->Application->HREF($t, '', $params);
}
/**
* Deprecated
*
* @param array $params
* @return int
* @deprecated Parameter "column_width" of "PrintList" tag does that
*/
function ColumnWidth($params)
{
$columns = $this->Application->Parser->GetParam('columns');
return round(100/$columns).'%';
}
/**
* Append prefix and special to tag
* params (get them from tagname) like
* they were really passed as params
*
* @param Array $tag_params
* @return Array
* @access protected
*/
function prepareTagParams($tag_params = Array())
{
$ret = $tag_params;
$ret['Prefix'] = $this->Prefix;
$ret['Special'] = $this->Special;
$ret['PrefixSpecial'] = $this->getPrefixSpecial();
return $ret;
}
function GetISO($currency, $field_currency = '')
{
if ( $currency == 'selected' ) {
return $this->Application->RecallVar('curr_iso');
}
if ( $currency == 'primary' || $currency == '' ) {
return $this->Application->GetPrimaryCurrency();
}
// explicit currency
return $currency == 'field' && $field_currency ? $field_currency : $currency;
}
/**
* Convert primary currency to selected (if they are the same, converter will just return)
*
* @param float $value
* @param string $target_iso
* @param string $source_iso
* @return float
*/
function ConvertCurrency($value, $target_iso, $source_iso = 'PRIMARY')
{
$converter = $this->Application->recallObject('CurrencyRates');
/* @var $converter CurrencyRates */
return $converter->Convert($value, $source_iso, $target_iso);
}
function AddCurrencySymbol($value, $iso, $decimal_tag = '')
{
$converter = $this->Application->recallObject('CurrencyRates');
/* @var $converter CurrencyRates */
return $converter->AddCurrencySymbol($value, $iso, $decimal_tag);
}
/**
* Get's requested field value
*
* @param Array $params
* @return string
* @access public
*/
function Field($params)
{
$field = $this->SelectParam($params, 'name,field');
if (!$this->Application->isAdmin) {
// don't apply kUtil::escape() on any field value on Front-End
$params['no_special'] = 'no_special';
}
$object = $this->getObject($params);
/* @var $object kDBItem */
if (array_key_exists('db', $params) && $params['db']) {
$value = $object->GetDBField($field);
}
else {
if (array_key_exists('currency', $params) && $params['currency']) {
$source_iso = isset($params['currency_field']) ? $object->GetDBField($params['currency_field']) : 'PRIMARY';
$target_iso = $this->GetISO($params['currency'], $source_iso);
$original = $object->GetDBField($field);
$value = $this->ConvertCurrency($original, $target_iso, $source_iso);
$object->SetDBField($field, $value);
$object->SetFieldOption($field, 'converted', true);
}
$format = array_key_exists('format', $params) ? $params['format'] : false;
if (!$format || $format == '$format') {
$format = NULL;
}
$value = $object->GetField($field, $format);
if (array_key_exists('negative', $params) && $params['negative']) {
if (strpos($value, '-') === 0) {
$value = substr($value, 1);
}
else {
$value = '-' . $value;
}
}
if (array_key_exists('currency', $params) && $params['currency']) {
$decimal_tag = isset($params['decimal_tag']) ? $params['decimal_tag'] : '';
$value = $this->AddCurrencySymbol($value, $target_iso, $decimal_tag);
$params['no_special'] = 1;
}
}
if (!array_key_exists('no_special', $params) || !$params['no_special']) {
$value = kUtil::escape($value);
}
if (array_key_exists('checked', $params) && $params['checked']) {
$value = ($value == ( isset($params['value']) ? $params['value'] : 1)) ? 'checked' : '';
}
if (array_key_exists('plus_or_as_label', $params) && $params['plus_or_as_label']) {
$value = substr($value, 0,1) == '+' ? substr($value, 1) : $this->Application->Phrase($value);
}
elseif (array_key_exists('as_label', $params) && $params['as_label']) {
$value = $this->Application->Phrase($value);
}
$first_chars = $this->SelectParam($params,'first_chars,cut_first');
if ($first_chars) {
$stripped_value = strip_tags($value, $this->SelectParam($params, 'allowed_tags'));
if ( mb_strlen($stripped_value) > $first_chars ) {
$value = preg_replace('/\s+?(\S+)?$/', '', mb_substr($stripped_value, 0, $first_chars + 1)) . ' ...';
}
}
if (array_key_exists('nl2br', $params) && $params['nl2br']) {
$value = nl2br($value);
}
if ($value != '') {
$this->Application->Parser->DataExists = true;
}
if (array_key_exists('currency', $params) && $params['currency']) {
// restoring value in original currency, for other Field tags to work properly
$object->SetDBField($field, $original);
}
return $value;
}
function FieldHintLabel($params)
{
if ( isset($params['direct_label']) && $params['direct_label'] ) {
$label = $params['direct_label'];
$hint = $this->Application->Phrase($label, false);
}
else {
$label = $params['title_label'];
$hint = $this->Application->Phrase('hint:' . $label, false);
}
return $hint != strtoupper('!' . $label . '!') ? $hint : ''; // $hint
}
/**
* Returns formatted date + time on current language
*
* @param $params
*/
function DateField($params)
{
$field = $this->SelectParam($params, 'name,field');
if ($field) {
$object = $this->getObject($params);
/* @var $object kDBItem */
$timestamp = $object->GetDBField($field);
}
else {
$timestamp = $params['value'];
}
$date = $timestamp;
// prepare phrase replacements
$replacements = Array (
'l' => 'la_WeekDay',
'D' => 'la_WeekDay',
'M' => 'la_Month',
'F' => 'la_Month',
);
// cases allow to append phrase suffix based on requested case (e.g. Genitive)
$case_suffixes = array_key_exists('case_suffixes', $params) ? $params['case_suffixes'] : false;
if ($case_suffixes) {
// apply case suffixes (for russian language only)
$case_suffixes = explode(',', $case_suffixes);
foreach ($case_suffixes as $case_suffux) {
list ($replacement_name, $case_suffix_value) = explode('=', $case_suffux, 2);
$replacements[$replacement_name] .= $case_suffix_value;
}
}
$format = array_key_exists('format', $params) ? $params['format'] : false;
if (preg_match('/_regional_(.*)/', $format, $regs)) {
$language = $this->Application->recallObject('lang.current');
/* @var $language kDBItem */
$format = $language->GetDBField($regs[1]);
}
elseif (!$format) {
$format = null;
}
// escape formats, that are resolved to words by `date`
foreach ($replacements as $format_char => $phrase_prefix) {
if (strpos($format, $format_char) === false) {
unset($replacements[$format_char]);
continue;
}
$replacements[$format_char] = $this->Application->Phrase($phrase_prefix . date($format_char, $date));
$format = str_replace($format_char, '#' . ord($format_char) . '#', $format);
}
$date_formatted = date($format, $date);
// unescape formats, that are resolved to words by `date`
foreach ($replacements as $format_char => $format_replacement) {
$date_formatted = str_replace('#' . ord($format_char) . '#', $format_replacement, $date_formatted);
}
return $date_formatted;
}
function SetField($params)
{
// <inp2:SetField field="Value" src=p:cust_{$custom_name}"/>
$object = $this->getObject($params);
/* @var $object kDBItem */
$dst_field = $this->SelectParam($params, 'name,field');
list($prefix_special, $src_field) = explode(':', $params['src']);
$src_object = $this->Application->recallObject($prefix_special);
/* @var $src_object kDBItem */
$object->SetDBField($dst_field, $src_object->GetDBField($src_field));
}
/**
* Depricated
*
* @param Array $params
* @return string
* @deprecated parameter "as_label" of "Field" tag does the same
*/
function PhraseField($params)
{
$field_label = $this->Field($params);
$translation = $this->Application->Phrase( $field_label );
return $translation;
}
function Error($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$field = $this->SelectParam($params, 'name,field');
return $object->GetErrorMsg($field, false);
}
function HasError($params)
{
if ($params['field'] == 'any') {
$object = $this->getObject($params);
/* @var $object kDBItem */
$skip_fields = array_key_exists('except', $params) ? $params['except'] : false;
$skip_fields = $skip_fields ? explode(',', $skip_fields) : Array();
return $object->HasErrors($skip_fields);
}
else {
$res = false;
$fields = explode(',', $this->SelectParam($params, 'field,fields'));
foreach ($fields as $field) {
// call kDBTagProcessor::Error instead of kDBItem::GetErrorPseudo to have ability to override Error tag
$params['field'] = $field;
$res = $res || ($this->Error($params) != '');
}
return $res;
}
}
/**
* Renders error message block, when there are errors on a form
*
* @param Array $params
* @return string
* @access protected
*/
protected function ErrorWarning($params)
{
if ( !isset($params['field']) ) {
$params['field'] = 'any';
}
if ( $this->HasError($params) ) {
$params['prefix'] = $this->getPrefixSpecial();
return $this->Application->ParseBlock($params);
}
return '';
}
function IsRequired($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$field = $params['field'];
$formatter_class = $object->GetFieldOption($field, 'formatter');
if ( $formatter_class == 'kMultiLanguage' ) {
$formatter = $this->Application->recallObject($formatter_class);
/* @var $formatter kMultiLanguage */
$field = $formatter->LangFieldName($field);
}
return $object->isRequired($field);
}
function FieldOption($params)
{
$object = $this->getObject($params);;
$options = $object->GetFieldOptions($params['field']);
$ret = isset($options[$params['option']]) ? $options[$params['option']] : '';
if (isset($params['as_label']) && $params['as_label']) $ret = $this->Application->ReplaceLanguageTags($ret);
return $ret;
}
/**
* Prints list a all possible field options
*
* @param Array $params
* @return string
* @access protected
*/
protected function PredefinedOptions($params)
{
$object = $this->getObject($params);
/* @var $object kDBList */
$field = $params['field'];
$value = array_key_exists('value', $params) ? $params['value'] : $object->GetDBField($field);
$field_options = $object->GetFieldOptions($field);
if (!array_key_exists('options', $field_options) || !is_array($field_options['options'])) {
trigger_error('Options not defined for <strong>'.$object->Prefix.'</strong> field <strong>'.$field.'</strong>', E_USER_WARNING);
return '';
}
$options = $field_options['options'];
if ( array_key_exists('has_empty', $params) && $params['has_empty'] ) {
$empty_value = array_key_exists('empty_value', $params) ? $params['empty_value'] : '';
$empty_label = isset($params['empty_label']) ? $params['empty_label'] : '';
if ( $empty_label ) {
if ( mb_substr($empty_label, 0, 1) == '+' ) {
// using plain text instead of phrase label
$empty_label = mb_substr($empty_label, 1);
}
else {
$empty_label = $this->Application->Phrase($empty_label, false);
}
}
// don't use other array merge function, because they will reset keys !!!
$options = kUtil::array_merge_recursive(Array ($empty_value => $empty_label), $options);
}
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
$block_params['pass_params'] = 'true';
if (method_exists($object, 'EOL') && count($object->Records) == 0) {
// for drawing grid column filter
$block_params['field_name'] = '';
}
else {
$block_params['field_name'] = $this->InputName($params); // depricated (produces warning when used as grid filter), but used in Front-End (submission create), admin (submission view)
}
$selected_param_name = array_key_exists('selected_param', $params) ? $params['selected_param'] : false;
if (!$selected_param_name) {
$selected_param_name = $params['selected'];
}
$selected = $params['selected'];
$o = '';
if (array_key_exists('no_empty', $params) && $params['no_empty'] && !getArrayValue($options, '')) {
// removes empty option, when present (needed?)
array_shift($options);
}
$index = 0;
$option_count = count($options);
if (strpos($value, '|') !== false) {
// multiple checkboxes OR multiselect
$value = explode('|', substr($value, 1, -1) );
foreach ($options as $key => $val) {
$block_params['key'] = $key;
$block_params['option'] = $val;
$block_params[$selected_param_name] = ( in_array($key, $value) ? ' '.$selected : '');
$block_params['is_last'] = $index == $option_count - 1;
$o .= $this->Application->ParseBlock($block_params);
$index++;
}
}
else {
// single selection radio OR checkboxes OR dropdown
foreach ($options as $key => $val) {
$block_params['key'] = $key;
$block_params['option'] = $val;
$block_params[$selected_param_name] = (strlen($key) == strlen($value) && ($key == $value) ? ' '.$selected : '');
$block_params['is_last'] = $index == $option_count - 1;
$o .= $this->Application->ParseBlock($block_params);
$index++;
}
}
return $o;
}
function PredefinedSearchOptions($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
$params['value'] = $this->SearchField($params);
return $this->PredefinedOptions($params);
}
function Format($params, $object = null)
{
$field = $this->SelectParam($params, 'name,field');
if ( !isset($object) ) {
$object = $this->getObject($params);
/* @var $object kDBItem */
}
$options = $object->GetFieldOptions($field);
$format = $options[$this->SelectParam($params, 'input_format') ? 'input_format' : 'format'];
$formatter_class = array_key_exists('formatter', $options) ? $options['formatter'] : false;
if ( $formatter_class ) {
$formatter = $this->Application->recallObject($formatter_class);
/* @var $formatter kFormatter */
$human_format = array_key_exists('human', $params) ? $params['human'] : false;
$edit_size = array_key_exists('edit_size', $params) ? $params['edit_size'] : false;
$sample = array_key_exists('sample', $params) ? $params['sample'] : false;
if ( $sample ) {
return $formatter->GetSample($field, $options, $object);
}
elseif ( $human_format || $edit_size ) {
$format = $formatter->HumanFormat($format);
return $edit_size ? strlen($format) : $format;
}
}
return $format;
}
/**
* Returns grid padination information
* Can return links to pages
*
* @param Array $params
* @return mixed
*/
function PageInfo($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
$type = $params['type'];
unset($params['type']); // remove parameters used only by current tag
$ret = '';
switch ($type) {
case 'current':
$ret = $object->GetPage();
break;
case 'total':
$ret = $object->GetTotalPages();
break;
case 'prev':
$ret = $object->GetPage() > 1 ? $object->GetPage() - 1 : false;
break;
case 'next':
$ret = $object->GetPage() < $object->GetTotalPages() ? $object->GetPage() + 1 : false;
break;
}
if ($ret && isset($params['as_link']) && $params['as_link']) {
unset($params['as_link']); // remove parameters used only by current tag
$params['page'] = $ret;
$current_page = $object->GetPage(); // backup current page
$ret = $this->PageLink($params);
$this->Application->SetVar($object->getPrefixSpecial().'_Page', $current_page); // restore page
}
return $ret;
}
/**
* Print grid pagination using
* block names specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintPages($params)
{
$list =& $this->GetList($params);
$prefix_special = $list->getPrefixSpecial();
$total_pages = $list->GetTotalPages();
if ( $total_pages > 1 ) {
$this->Application->Parser->DataExists = true;
}
if ( $total_pages == 0 ) {
// display 1st page as selected in case if we have no pages at all
$total_pages = 1;
}
$o = '';
// what are these 2 lines for?
$this->Application->SetVar($prefix_special . '_event', '');
$this->Application->SetVar($prefix_special . '_id', '');
$current_page = $list->GetPage(); // $this->Application->RecallVar($prefix_special.'_Page');
$block_params = $this->prepareTagParams($params);
$split = (isset($params['split']) ? $params['split'] : 10);
$split_start = $current_page - ceil($split / 2);
if ( $split_start < 1 ) {
$split_start = 1;
}
$split_end = $split_start + $split - 1;
if ( $split_end > $total_pages ) {
$split_end = $total_pages;
$split_start = max($split_end - $split + 1, 1);
}
if ( $current_page > 1 ) {
$prev_block_params = $this->prepareTagParams($params);
if ( $total_pages > $split ) {
$prev_block_params['page'] = max($current_page - $split, 1);
$prev_block_params['name'] = $this->SelectParam($params, 'prev_page_split_render_as,prev_page_split_block');
if ( $prev_block_params['name'] ) {
$o .= $this->Application->ParseBlock($prev_block_params);
}
}
$prev_block_params['name'] = 'page';
$prev_block_params['page'] = $current_page - 1;
$prev_block_params['name'] = $this->SelectParam($params, 'prev_page_render_as,block_prev_page,prev_page_block');
if ( $prev_block_params['name'] ) {
$this->Application->SetVar($this->getPrefixSpecial() . '_Page', $current_page - 1);
$o .= $this->Application->ParseBlock($prev_block_params);
}
}
else {
$no_prev_page_block = $this->SelectParam($params, 'no_prev_page_render_as,block_no_prev_page');
if ( $no_prev_page_block ) {
$block_params['name'] = $no_prev_page_block;
$o .= $this->Application->ParseBlock($block_params);
}
}
$total_records = $list->GetRecordsCount();
$separator_params['name'] = $this->SelectParam($params, 'separator_render_as,block_separator');
for ($i = $split_start; $i <= $split_end; $i++) {
$from_record = ($i - 1) * $list->GetPerPage();
$to_record = $from_record + $list->GetPerPage();
if ( $to_record > $total_records ) {
$to_record = $total_records;
}
$block_params['from_record'] = $from_record + 1;
$block_params['to_record'] = $to_record;
if ( $i == $current_page ) {
$block = $this->SelectParam($params, 'current_render_as,active_render_as,block_current,active_block');
}
else {
$block = $this->SelectParam($params, 'link_render_as,inactive_render_as,block_link,inactive_block');
}
$block_params['name'] = $block;
$block_params['page'] = $i;
$this->Application->SetVar($this->getPrefixSpecial() . '_Page', $i);
$o .= $this->Application->ParseBlock($block_params);
if ( $this->SelectParam($params, 'separator_render_as,block_separator') && $i < $split_end ) {
$o .= $this->Application->ParseBlock($separator_params);
}
}
if ( $current_page < $total_pages ) {
$next_block_params = $this->prepareTagParams($params);
$next_block_params['page'] = $current_page + 1;
$next_block_params['name'] = $this->SelectParam($params, 'next_page_render_as,block_next_page,next_page_block');
if ( $next_block_params['name'] ) {
$this->Application->SetVar($this->getPrefixSpecial() . '_Page', $current_page + 1);
$o .= $this->Application->ParseBlock($next_block_params);
}
if ( $total_pages > $split ) {
$next_block_params['page'] = min($current_page + $split, $total_pages);
$next_block_params['name'] = $this->SelectParam($params, 'next_page_split_render_as,next_page_split_block');
if ( $next_block_params['name'] ) {
$o .= $this->Application->ParseBlock($next_block_params);
}
}
}
else {
$no_next_page_block = $this->SelectParam($params, 'no_next_page_render_as,block_no_next_page');
if ( $no_next_page_block ) {
$block_params['name'] = $no_next_page_block;
$o .= $this->Application->ParseBlock($block_params);
}
}
$this->Application->SetVar($this->getPrefixSpecial() . '_Page', $current_page);
return $o;
}
/**
* Print grid pagination using
* block names specified
*
* @param Array $params
* @return string
* @access public
*/
function PaginationBar($params)
{
return $this->PrintPages($params);
}
function PerPageBar($params)
{
$object =& $this->GetList($params);
$ret = '';
$per_pages = explode(';', $params['per_pages']);
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
foreach ($per_pages as $per_page) {
$block_params['per_page'] = $per_page;
$this->Application->SetVar($this->getPrefixSpecial() . '_PerPage', $per_page);
$block_params['selected'] = $per_page == $object->GetPerPage();
$ret .= $this->Application->ParseBlock($block_params, 1);
}
$this->Application->SetVar($this->getPrefixSpecial() . '_PerPage', $object->GetPerPage());
return $ret;
}
/**
* Returns field name (processed by kMultiLanguage formatter
* if required) and item's id from it's IDField or field required
*
* @param Array $params
* @return Array (id,field)
* @access private
*/
function prepareInputName($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$field = $this->SelectParam($params, 'name,field');
$formatter_class = $object->GetFieldOption($field, 'formatter');
if ($formatter_class == 'kMultiLanguage') {
$formatter = $this->Application->recallObject($formatter_class);
/* @var $formatter kMultiLanguage */
$force_primary = $object->GetFieldOption($field, 'force_primary');
$field = $formatter->LangFieldName($field, $force_primary);
}
if (array_key_exists('force_id', $params)) {
$id = $params['force_id'];
}
else {
$id_field = array_key_exists('IdField', $params) ? $params['IdField'] : false;
$id = $id_field ? $object->GetDBField($id_field) : $object->GetID();
}
return Array($id, $field);
}
/**
* Returns input field name to
* be placed on form (for correct
* event processing)
*
* @param Array $params
* @return string
* @access public
*/
function InputName($params)
{
list($id, $field) = $this->prepareInputName($params);
$ret = $this->getPrefixSpecial().'['.$id.']['.$field.']';
if (array_key_exists('as_preg', $params) && $params['as_preg']) {
$ret = preg_quote($ret, '/');
}
return $ret;
}
/**
* Allows to override various field options through hidden fields with specific names in submit.
* This tag generates this special names
*
* @param Array $params
* @return string
* @author Alex
*/
function FieldModifier($params)
{
list($id, $field) = $this->prepareInputName($params);
$ret = 'field_modifiers['.$this->getPrefixSpecial().']['.$field.']['.$params['type'].']';
if (array_key_exists('as_preg', $params) && $params['as_preg']) {
$ret = preg_quote($ret, '/');
}
if (isset($params['value'])) {
$object = $this->getObject($params);
$field_modifiers[$field][$params['type']] = $params['value'];
$object->ApplyFieldModifiers($field_modifiers);
}
return $ret;
}
/**
* Returns index where 1st changeable sorting field begins
*
* @return int
* @access private
*/
function getUserSortIndex()
{
$list_sortings = $this->getUnitConfig()->getListSortingsBySpecial($this, Array ());
$user_sorting_start = 0;
$forced_sorting = getArrayValue($list_sortings, 'ForcedSorting');
return $forced_sorting ? count($forced_sorting) : $user_sorting_start;
}
/**
* Returns order direction for given field
*
*
*
* @param Array $params
* @return string
* @access public
*/
function Order($params)
{
$field = $params['field'];
$user_sorting_start = $this->getUserSortIndex();
$list =& $this->GetList($params);
if ($list->GetOrderField($user_sorting_start) == $field)
{
return strtolower($list->GetOrderDirection($user_sorting_start));
}
elseif($this->Application->ConfigValue('UseDoubleSorting') && $list->GetOrderField($user_sorting_start+1) == $field)
{
return '2_'.strtolower($list->GetOrderDirection($user_sorting_start+1));
}
else
{
return 'no';
}
}
/**
* Detects, that current sorting is not default
*
* @param Array $params
* @return bool
*/
function OrderChanged($params)
{
$list =& $this->GetList($params);
$list_helper = $this->Application->recallObject('ListHelper');
/* @var $list_helper ListHelper */
return $list_helper->hasUserSorting($list);
}
/**
* Gets information of sorting field at "pos" position,
* like sorting field name (type="field") or sorting direction (type="direction")
*
* @param Array $params
* @return string
* @access protected
*/
protected function OrderInfo($params)
{
$user_sorting_start = $this->getUserSortIndex() + --$params['pos'];
$list =& $this->GetList($params);
if ( $params['type'] == 'field' ) {
return $list->GetOrderField($user_sorting_start);
}
if ( $params['type'] == 'direction' ) {
return $list->GetOrderDirection($user_sorting_start);
}
return '';
}
/**
* Checks if sorting field/direction matches passed field/direction parameter
*
* @param Array $params
* @return bool
* @access protected
*/
protected function IsOrder($params)
{
$params['type'] = isset($params['field']) ? 'field' : 'direction';
$value = $this->OrderInfo($params);
if ( isset($params['field']) ) {
return $params['field'] == $value;
}
elseif ( isset($params['direction']) ) {
return $params['direction'] == $value;
}
return false;
}
/**
* Returns list per-page
*
* @param Array $params
* @return int
*/
function PerPage($params)
{
$object =& $this->GetList($params);
return $object->GetPerPage();
}
/**
* Checks if list perpage matches value specified
*
* @param Array $params
* @return bool
*/
function PerPageEquals($params)
{
$object =& $this->GetList($params);
return $object->GetPerPage() == $params['value'];
}
function SaveEvent($params)
{
// SaveEvent is set during OnItemBuild, but we may need it before any other tag calls OnItemBuild
$object = $this->getObject($params);
return $this->Application->GetVar($this->getPrefixSpecial().'_SaveEvent');
}
function NextId($params)
{
$object = $this->getObject($params);
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ids = explode(',', $this->Application->RecallVar($session_name));
$cur_id = $object->GetID();
$i = array_search($cur_id, $ids);
if ($i !== false) {
return $i < count($ids) - 1 ? $ids[$i + 1] : '';
}
return '';
}
function PrevId($params)
{
$object = $this->getObject($params);
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ids = explode(',', $this->Application->RecallVar($session_name));
$cur_id = $object->GetID();
$i = array_search($cur_id, $ids);
if ($i !== false) {
return $i > 0 ? $ids[$i - 1] : '';
}
return '';
}
function IsSingle($params)
{
return ($this->NextId($params) === '' && $this->PrevId($params) === '');
}
function IsLast($params)
{
return ($this->NextId($params) === '');
}
function IsFirst($params)
{
return ($this->PrevId($params) === '');
}
/**
* Checks if field value is equal to proposed one
*
* @param Array $params
* @return bool
* @deprecated
*/
function FieldEquals($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
return $object->GetDBField( $this->SelectParam($params, 'name,field') ) == $params['value'];
}
/**
* Checks, that grid has icons defined and they should be shown
*
* @param Array $params
* @return bool
*/
function UseItemIcons($params)
{
return array_key_exists('Icons', $this->getUnitConfig()->getGridByName($params['grid']));
}
/**
* Returns corresponding to grid layout selector column width
*
* @param Array $params
* @return int
*/
function GridSelectorColumnWidth($params)
{
$width = 0;
if ($params['selector']) {
$width += $params['selector_width'];
}
if ($this->UseItemIcons($params)) {
$width += $params['icon_width'];
}
return $width;
}
/**
* Returns grids item selection mode (checkbox, radio, )
*
* @param Array $params
* @return string
*/
function GridSelector($params)
{
$grid = $this->getUnitConfig()->getGridByName($params['grid']);
return array_key_exists('Selector', $grid) ? $grid['Selector'] : $params['default'];
}
function ItemIcon($params)
{
$config = $this->getUnitConfig();
$grid = $config->getGridByName($params['grid']);
if ( !isset($grid['Icons']) ) {
return '';
}
$icons = $grid['Icons'];
if ( isset($params['name']) ) {
$icon_name = $params['name'];
return isset($icons[$icon_name]) ? $icons[$icon_name] : '';
}
$status_fields = $config->getStatusField(false, Array ());
if ( !$status_fields ) {
return $icons['default'];
}
$object = $this->getObject($params);
/* @var $object kDBList */
$icon = '';
foreach ($status_fields as $status_field) {
$icon .= $object->GetDBField($status_field) . '_';
}
$icon = rtrim($icon, '_');
return isset($icons[$icon]) ? $icons[$icon] : $icons['default'];
}
/**
* Generates bluebar title + initializes prefixes used on page
*
* @param Array $params
* @return string
*/
function SectionTitle($params)
{
$config = $this->getUnitConfig();
$preset_name = kUtil::replaceModuleSection($params['title_preset']);
$title_info = $config->getTitlePresetByName($preset_name);
if ( $title_info === false ) {
$title = str_replace('#preset_name#', $preset_name, $params['title']);
if ( $this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title'] ) {
$title .= ' - ' . $params['group_title'];
}
return $title;
}
$default_title_preset = $config->getTitlePresetByName('default');
if ( $default_title_preset ) {
// use default labels + custom labels specified in preset used
$title_info = kUtil::array_merge_recursive($default_title_preset, $title_info);
}
$title = $title_info['format'];
// 1. get objects in use for title construction
$objects = Array ();
$object_status = Array ();
$status_labels = Array ();
$prefixes = array_key_exists('prefixes', $title_info) ? $title_info['prefixes'] : false;
$all_tag_params = array_key_exists('tag_params', $title_info) ? $title_info['tag_params'] : false;
/* @var $prefixes Array */
if ( $prefixes ) {
// extract tag_params passed directly to SectionTitle tag for specific prefix
foreach ($params as $tp_name => $tp_value) {
if ( preg_match('/(.*)\[(.*)\]/', $tp_name, $regs) ) {
$all_tag_params[$regs[1]][$regs[2]] = $tp_value;
unset($params[$tp_name]);
}
}
$tag_params = Array ();
foreach ($prefixes as $prefix_special) {
$prefix_data = $this->Application->processPrefix($prefix_special);
$prefix_data['prefix_special'] = rtrim($prefix_data['prefix_special'], '.');
if ( $all_tag_params ) {
$tag_params = getArrayValue($all_tag_params, $prefix_data['prefix_special']);
if ( !$tag_params ) {
$tag_params = Array ();
}
}
$tag_params = array_merge($params, $tag_params);
$objects[$prefix_data['prefix_special']] = $this->Application->recallObject($prefix_data['prefix_special'], $prefix_data['prefix'], $tag_params);
$object_status[$prefix_data['prefix_special']] = $objects[$prefix_data['prefix_special']]->IsNewItem() ? 'new' : 'edit';
// a. set object's status field (adding item/editing item) for each object in title
if ( getArrayValue($title_info[$object_status[$prefix_data['prefix_special']] . '_status_labels'], $prefix_data['prefix_special']) ) {
$status_labels[$prefix_data['prefix_special']] = $title_info[$object_status[$prefix_data['prefix_special']] . '_status_labels'][$prefix_data['prefix_special']];
$title = str_replace('#' . $prefix_data['prefix_special'] . '_status#', $status_labels[$prefix_data['prefix_special']], $title);
}
// b. setting object's titlefield value (in titlebar ONLY) to default in case if object beeing created with no titlefield filled in
if ( $object_status[$prefix_data['prefix_special']] == 'new' ) {
$new_value = $this->getInfo($objects[$prefix_data['prefix_special']], 'titlefield');
if ( !$new_value && getArrayValue($title_info['new_titlefield'], $prefix_data['prefix_special']) ) {
$new_value = $this->Application->Phrase($title_info['new_titlefield'][$prefix_data['prefix_special']]);
}
$title = str_replace('#' . $prefix_data['prefix_special'] . '_titlefield#', $new_value, $title);
}
}
}
// replace to section title
$section = array_key_exists('section', $params) ? $params['section'] : false;
if ( $section ) {
$sections_helper = $this->Application->recallObject('SectionsHelper');
/* @var $sections_helper kSectionsHelper */
$section_data =& $sections_helper->getSectionData($section);
$title = str_replace('#section_label#', '!' . $section_data['label'] . '!', $title);
}
// 2. replace phrases if any found in format string
$title = $this->Application->ReplaceLanguageTags($title, false);
// 3. find and replace any replacement vars
preg_match_all('/#(.*_.*)#/Uis', $title, $rets);
if ( $rets[1] ) {
$replacement_vars = array_keys(array_flip($rets[1]));
foreach ($replacement_vars as $replacement_var) {
$var_info = explode('_', $replacement_var, 2);
$object =& $objects[$var_info[0]];
$new_value = $this->getInfo($object, $var_info[1]);
$title = str_replace('#' . $replacement_var . '#', $new_value, $title);
}
}
// replace trailing spaces inside title preset + '' occurrences into single space
$title = preg_replace('/[ ]*\'\'[ ]*/', ' ', $title);
if ( $this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title'] ) {
$title .= ' - ' . $params['group_title'];
}
$first_chars = $this->SelectParam($params, 'first_chars,cut_first');
if ( $first_chars && !preg_match('/<a href="(.*)".*>(.*)<\/a>/', $title) ) {
// don't cut titles, that contain phrase translation links
$stripped_title = strip_tags($title, $this->SelectParam($params, 'allowed_tags'));
if ( mb_strlen($stripped_title) > $first_chars ) {
$title = mb_substr($stripped_title, 0, $first_chars) . ' ...';
}
}
return $title;
}
/**
* Returns information about list
*
* @param kDBList $object
* @param string $info_type
* @return string
* @access protected
*/
protected function getInfo(&$object, $info_type)
{
switch ( $info_type ) {
case 'titlefield':
$field = $object->getUnitConfig()->getTitleField();
return $field !== false ? $object->GetField($field) : 'TitleField Missing';
break;
case 'recordcount':
if ( $object->GetRecordsCount(false) != $object->GetRecordsCount() ) {
$of_phrase = $this->Application->Phrase('lc_of');
return $object->GetRecordsCount() . ' ' . $of_phrase . ' ' . $object->GetRecordsCount(false);
}
return $object->GetRecordsCount();
break;
}
return $object->GetField($info_type);
}
function GridInfo($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
switch ( $params['type'] ) {
case 'filtered':
return $object->GetRecordsCount();
case 'total':
return $object->GetRecordsCount(false);
case 'from':
return $object->GetRecordsCount() ? $object->GetOffset() + 1 : 0; //0-based
case 'to':
$record_count = $object->GetRecordsCount();
return $object->GetPerPage(true) != -1 ? min($object->GetOffset() + $object->GetPerPage(), $record_count) : $record_count;
case 'total_pages':
return $object->GetTotalPages();
case 'needs_pagination':
return ($object->GetPerPage(true) != -1) && (($object->GetRecordsCount() > $object->GetPerPage()) || ($object->GetPage() > 1));
}
return false;
}
/**
* Parses block depending on its element type.
* For radio and select elements values are taken from 'value_list_field' in key1=value1,key2=value2
* format. key=value can be substituted by <SQL>SELECT f1 AS OptionName, f2 AS OptionValue... FROM <PREFIX>TableName </SQL>
* where prefix is TABLE_PREFIX
*
* @param Array $params
* @return string
*/
function ConfigFormElement($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$field = $params['field'];
$helper = $this->Application->recallObject('InpCustomFieldsHelper');
/* @var $helper InpCustomFieldsHelper */
$element_type = $object->GetDBField($params['element_type_field']);
if ($element_type == 'label') {
$element_type = 'text';
}
$formatter_class = $object->GetFieldOption($field, 'formatter');
switch ($element_type) {
case 'select':
case 'multiselect':
case 'radio':
if ($object->GetDBField('DirectOptions')) {
// used for custom fields
$options = $object->GetDBField('DirectOptions');
}
else {
// used for configuration
$options = $helper->GetValuesHash( $object->GetDBField($params['value_list_field']) );
}
$object->SetFieldOption($field, 'formatter', 'kOptionsFormatter');
$object->SetFieldOption($field, 'options', $options);
break;
case 'text':
case 'textarea':
case 'upload':
$params['field_params'] = $helper->ParseConfigSQL($object->GetDBField($params['value_list_field']));
break;
case 'password':
case 'checkbox':
default:
break;
}
if (!$element_type) {
throw new Exception('Element type missing for "<strong>' . $object->GetDBField('VariableName') . '</strong>" configuration variable');
}
$params['name'] = $params['blocks_prefix'] . $element_type;
// use $pass_params to pass 'SourcePrefix' parameter from PrintList to CustomInputName tag
$ret = $this->Application->ParseBlock($params, 1);
$object->SetFieldOption($field, 'formatter', $formatter_class);
return $ret;
}
/**
* Get's requested custom field value
*
* @param Array $params
* @return string
* @access public
*/
function CustomField($params)
{
$params['name'] = 'cust_'.$this->SelectParam($params, 'name,field');
return $this->Field($params);
}
function CustomFieldLabel($params)
{
$object = $this->getObject($params);
$field = $this->SelectParam($params, 'name,field');
$sql = 'SELECT FieldLabel
FROM ' . $this->Application->getUnitConfig('cf')->getTableName() . '
WHERE FieldName = ' . $this->Conn->qstr($field);
return $this->Application->Phrase($this->Conn->GetOne($sql));
}
/**
* transposes 1-dimensional array elements for vertical alignment according to given columns and per_page parameters
*
* @param array $arr
* @param int $columns
* @param int $per_page
* @return array
*/
function LinearToVertical(&$arr, $columns, $per_page)
{
$rows = $columns;
// in case if after applying per_page limit record count less then
// can fill requrested column count, then fill as much as we can
$cols = min(ceil($per_page / $columns), ceil(count($arr) / $columns));
$imatrix = array();
for ($row = 0; $row < $rows; $row++) {
for ($col = 0; $col < $cols; $col++) {
$source_index = $row * $cols + $col;
if (!isset($arr[$source_index])) {
// in case if source array element count is less then element count in one row
continue;
}
$imatrix[$col * $rows + $row] = $arr[$source_index];
}
}
ksort($imatrix);
return array_values($imatrix);
}
/**
* If data was modified & is in TempTables mode, then parse block with name passed;
* remove modification mark if not in TempTables mode
*
* @param Array $params
* @return string
* @access protected
*/
protected function SaveWarning($params)
{
$main_prefix = array_key_exists('main_prefix', $params) ? $params['main_prefix'] : false;
if ( $main_prefix ) {
$top_prefix = $main_prefix;
}
else {
$top_prefix = $this->Application->GetTopmostPrefix($this->Prefix);
}
$temp_tables = substr($this->Application->GetVar($top_prefix . '_mode'), 0, 1) == 't';
$modified = $this->Application->RecallVar($top_prefix . '_modified');
if ( $temp_tables && $modified ) {
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,name');
$block_params['edit_mode'] = $temp_tables ? 1 : 0;
return $this->Application->ParseBlock($block_params);
}
$this->Application->RemoveVar($top_prefix . '_modified');
return '';
}
/**
* Returns list record count queries (on all pages)
*
* @param Array $params
* @return int
*/
function TotalRecords($params)
{
$list =& $this->GetList($params);
return $list->GetRecordsCount();
}
/**
* Range filter field name
*
* @param Array $params
* @return string
*/
function SearchInputName($params)
{
$field = $this->SelectParam($params, 'field,name');
$ret = 'custom_filters['.$this->getPrefixSpecial().']['.$params['grid'].']['.$field.']['.$params['filter_type'].']';
if (isset($params['type'])) {
$ret .= '['.$params['type'].']';
}
if (array_key_exists('as_preg', $params) && $params['as_preg']) {
$ret = preg_quote($ret, '/');
}
return $ret;
}
/**
* Return range filter field value
*
* @param Array $params
* @return string
* @access protected
*/
protected function SearchField($params) // RangeValue
{
$field = $this->SelectParam($params, 'field,name');
$view_name = $this->Application->RecallVar($this->getPrefixSpecial() . '_current_view');
$custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial() . '_custom_filter.' . $view_name /*, ALLOW_DEFAULT_SETTINGS*/);
$custom_filter = $custom_filter ? unserialize($custom_filter) : Array ();
if ( isset($custom_filter[$params['grid']][$field]) ) {
$ret = $custom_filter[$params['grid']][$field][$params['filter_type']]['submit_value'];
if ( isset($params['type']) ) {
$ret = $ret[$params['type']];
}
if ( array_key_exists('formatted', $params) && $params['formatted'] ) {
$object =& $this->GetList($params);
$formatter_class = $object->GetFieldOption($field, 'formatter');
if ( $formatter_class ) {
$formatter = $this->Application->recallObject($formatter_class);
/* @var $formatter kFormatter */
$ret = $formatter->Format($ret, $field, $object);
}
}
if ( !array_key_exists('no_special', $params) || !$params['no_special'] ) {
$ret = kUtil::escape($ret);
}
return $ret;
}
return '';
}
/**
* Tells, that at least one of search filters is used by now
*
* @param Array $params
* @return bool
*/
function SearchActive($params)
{
if ($this->Application->RecallVar($this->getPrefixSpecial() . '_search_keyword')) {
// simple search filter is used
return true;
}
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
$custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_custom_filter.'.$view_name/*, ALLOW_DEFAULT_SETTINGS*/);
$custom_filter = $custom_filter ? unserialize($custom_filter) : Array();
return array_key_exists($params['grid'], $custom_filter);
}
function SearchFormat($params)
{
$object =& $this->GetList($params);
return $this->Format($params, $object);
}
/**
* Returns error of range field
*
* @param Array $params
* @return string
* @access protected
*/
protected function SearchError($params)
{
$field = $this->SelectParam($params, 'field,name');
$error_var_name = $this->getPrefixSpecial() . '_' . $field . '_error';
$pseudo = $this->Application->RecallVar($error_var_name);
if ( $pseudo ) {
$this->Application->RemoveVar($error_var_name);
}
$object = $this->Application->recallObject($this->Prefix . '.' . $this->Special . '-item', null, Array ('skip_autoload' => true));
/* @var $object kDBItem */
$object->SetError($field, $pseudo);
return $object->GetErrorMsg($field, false);
}
/**
* Returns object used in tag processor
*
* @param Array $params
* @access public
* @return kDBItem|kDBList
*/
function getObject($params = Array())
{
$object = $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params);
/* @var $object kDBItem */
if ( isset($params['requery']) && $params['requery'] ) {
$this->Application->HandleEvent(new kEvent($this->getPrefixSpecial() . ':LoadItem', $params));
}
return $object;
}
/**
* Checks if object propery value matches value passed
*
* @param Array $params
* @return bool
*/
function PropertyEquals($params)
{
$object = $this->getObject($params);
$property_name = $this->SelectParam($params, 'name,var,property');
return $object->$property_name == $params['value'];
}
function DisplayOriginal($params)
{
return false;
}
/*function MultipleEditing($params)
{
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$selected_ids = explode(',', $this->Application->RecallVar($session_name));
$ret = '';
if ($selected_ids) {
$selected_ids = explode(',', $selected_ids);
$object = $this->getObject( kUtil::array_merge_recursive($params, Array('skip_autoload' => true)) );
$params['name'] = $params['render_as'];
foreach ($selected_ids as $id) {
$object->Load($id);
$ret .= $this->Application->ParseBlock($params);
}
}
return $ret;
}*/
/**
* Returns import/export process percent
*
* @param Array $params
* @return int
* @deprecated Please convert to event-model, not tag based
*/
function ExportStatus($params)
{
$export_object = $this->Application->recallObject('CatItemExportHelper');
/* @var $export_object kCatDBItemExportHelper */
$event = new kEvent($this->getPrefixSpecial().':OnDummy');
$action_method = 'perform'.ucfirst($this->Special);
$field_values = $export_object->$action_method($event);
// finish code is done from JS now
if ($field_values['start_from'] >= $field_values['total_records'])
{
if ($this->Special == 'import') {
// this is used?
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
$this->Application->Redirect('categories/cache_updater', Array('m_opener' => 'r', 'pass' => 'm', 'continue' => 1, 'no_amp' => 1));
}
elseif ($this->Special == 'export') {
// used for orders export in In-Commerce
$finish_t = $this->Application->RecallVar('export_finish_t');
$this->Application->Redirect($finish_t, Array('pass' => 'all'));
$this->Application->RemoveVar('export_finish_t');
}
}
$export_options = $export_object->loadOptions($event);
return $export_options['start_from'] * 100 / $export_options['total_records'];
}
/**
* Returns path where exported category items should be saved
*
* @param Array $params
* @return string
* @access protected
*/
protected function ExportPath($params)
{
$export_options = unserialize($this->Application->RecallVar($this->getPrefixSpecial() . '_options'));
$extension = $export_options['ExportFormat'] == 1 ? 'csv' : 'xml';
$filename = preg_replace('/(.*)\.' . $extension . '$/', '\1', $export_options['ExportFilename']) . '.' . $extension;
$path = EXPORT_PATH . '/';
if ( array_key_exists('as_url', $params) && $params['as_url'] ) {
$path = str_replace(FULL_PATH . '/', $this->Application->BaseURL(), $path);
}
return $path . $filename;
}
function FieldTotal($params)
{
$list =& $this->GetList($params);
$field = $this->SelectParam($params, 'field,name');
$total_function = array_key_exists('function', $params) ? $params['function'] : $list->getTotalFunction($field);
if (array_key_exists('function_only', $params) && $params['function_only']) {
return $total_function;
}
if (array_key_exists('currency', $params) && $params['currency']) {
$iso = $this->GetISO($params['currency']);
$original = $list->getTotal($field, $total_function);
$value = $this->ConvertCurrency($original, $iso);
$list->setTotal($field, $total_function, $value);
}
$value = $list->GetFormattedTotal($field, $total_function);
if (array_key_exists('currency', $params) && $params['currency']) {
$value = $this->AddCurrencySymbol($value, $iso);
}
return $value;
}
- /**
- * Returns FCKEditor locale, that matches default site language
- *
- * @return string
- */
- function _getFCKLanguage()
+ function FCKEditor($params)
{
- static $language_code = null;
-
- if ( !isset($language_code) ) {
- $language_code = 'en'; // default value
-
- if ( $this->Application->isAdmin ) {
- $language_id = $this->Application->Phrases->LanguageId;
- }
- else {
- $language_id = $this->Application->GetDefaultLanguageId(); // $this->Application->GetVar('m_lang');
- }
+ $editor_name = array_key_exists('name', $params) ? $params['name'] : $this->InputName($params);
- $sql = 'SELECT Locale
- FROM ' . $this->Application->getUnitConfig('lang')->getTableName() . '
- WHERE LanguageId = ' . $language_id;
- $locale = strtolower($this->Conn->GetOne($sql));
-
- if ( file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale . '.js') ) {
- // found language file, that exactly matches locale name (e.g. "en")
- $language_code = $locale;
- }
- else {
- $locale = explode('-', $locale);
+ $fck_helper = $this->Application->recallObject('FCKHelper');
+ /* @var $fck_helper fckFCKHelper */
- if ( file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale[0] . '.js') ) {
- // language file matches first part of locale (e.g. "ru-RU")
- $language_code = $locale[0];
- }
- }
+ if ( isset($params['mode']) && $params['mode'] == 'inline' ) {
+ return $fck_helper->CKEditorInlineTag($editor_name, $params);
}
- return $language_code;
+ return $fck_helper->CKEditorTag($editor_name, $this->CKEditorValue($params), $params);
}
-
- function FCKEditor($params)
+ /**
+ * Returns value, used by FCKEditor tag
+ *
+ * @param array $params
+ *
+ * @return string
+ */
+ protected function CKEditorValue($params)
{
$params['no_special'] = 1;
$params['format'] = array_key_exists('format', $params) ? $params['format'] . ';fck_ready' : 'fck_ready';
- $value = $this->Field($params);
- $name = array_key_exists('name', $params) ? $params['name'] : $this->InputName($params);
-
- $theme_path = $this->Application->GetFrontThemePath() . '/inc';
-
- if ( file_exists(FULL_PATH . $theme_path . '/style.css') ) {
- $url_params = Array (
- 'events[fck]' => 'OnGetsEditorStyles',
- 'no_pass_through' => 1, 'pass' => 'm', 'no_amp' => 1
- );
-
- $styles_css = $this->Application->HREF('index', '_FRONT_END_', $url_params, 'index.php');
- }
- else {
- $theme_path = rtrim(EDITOR_PATH, '/');
- $styles_css = $this->Application->BaseURL($theme_path) . 'style.css';
- }
-
- $styles_js = $this->Application->BaseURL($theme_path) . 'styles.js';
-
- $page_id = $this->Application->GetVar('c_id');
- $content_id = $this->Application->GetVar('content_id');
- $preview_url = '';
-
- /*if ($page_id && $content_id) {
- // editing content block from Front-End, not category in admin
- $categories_config = $this->Application->getUnitConfig('c');
-
- $sql = 'SELECT NamedParentPath
- FROM ' . $categories_config->getTableName() . '
- WHERE ' . $categories_config->getIDField() . ' = ' . (int)$page_id;
- $template = strtolower( $this->Conn->GetOne($sql) );
-
- $url_params = Array ('m_cat_id' => $page_id, 'no_amp' => 1, 'editing_mode' => EDITING_MODE_CONTENT, 'pass' => 'm');
- $preview_url = $this->Application->HREF($template, '_FRONT_END_', $url_params, 'index.php');
- $preview_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $preview_url);
- }*/
-
- include_once(FULL_PATH . EDITOR_PATH . 'ckeditor.php');
- $oCKeditor = new CKeditor(BASE_PATH . EDITOR_PATH);
-
-// $oFCKeditor->FullUrl = $this->Application->BaseURL();
-// $oFCKeditor->BaseUrl = BASE_PATH . '/'; // used by custom document plugin
-// $oFCKeditor->PreviewUrl = $preview_url; // used by custom MyPreview plugin
-
- $oCKeditor->lateLoad = array_key_exists('late_load', $params) && $params['late_load'];
-
- $width = $params['width'];
- $height = $params['height'];
-
- if ( preg_match('/^[\d]+$/', $width) ) {
- $width .= 'px';
- }
-
- if ( preg_match('/^[\d]+$/', $height) ) {
- $height .= 'px';
- }
-
- $oCKeditor->textareaAttributes = Array (
- 'style' => 'width: ' . $width . '; height: ' . $height . ';'
- );
-
- if ( file_exists(SYSTEM_PRESET_PATH . DIRECTORY_SEPARATOR . 'inp_ckconfig.js') ) {
- $file_helper = $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- $config_js = $file_helper->pathToUrl(SYSTEM_PRESET_PATH . DIRECTORY_SEPARATOR . 'inp_ckconfig.js');
- }
- else {
- $config_js = $this->Application->BaseURL() . 'core/admin_templates/js/inp_ckconfig.js';
- }
-
- $fck_helper = $this->Application->recallObject('FCKHelper');
- /* @var $fck_helper fckFCKHelper */
-
- $transit_params = $fck_helper->getTransitParams($params);
-
- $oCKeditor->config = Array (
- 'toolbar' => $this->Application->isDebugMode() ? 'DebugMode' : 'Default', // $page_id && $content_id ? 'Advanced' : 'Default',
-
- 'baseHref' => $this->Application->BaseURL( rtrim(EDITOR_PATH, '/') ),
-
-// 'ProjectPath' => BASE_PATH . '/', // used by custom MyPreview plugin
-
- 'customConfig' => $config_js,
- 'stylesSet' => 'portal:' . $styles_js,
- 'contentsCss' => $styles_css,
-// 'DefaultStyleLabel' => $this->Application->Phrase('la_editor_default_style'), // not ported to ckeditor
- 'Admin' => 1, // for custom file browser to work
- 'K4' => 1, // for custom file browser to work
-// 'PreviewUrl' => $preview_url,
-// 'BaseUrl' => BASE_PATH . '/', // used by custom document plugin & by file browser
- 'language' => $this->_getFCKLanguage(),
- 'height' => $height, // editor area height
- );
-
- if ( isset($transit_params['bgcolor']) && $transit_params['bgcolor'] ) {
- $oCKeditor->config['extraCss'] = 'body { background-color: ' . $transit_params['bgcolor'] . '; }';
- }
-
- foreach ($transit_params as $param_name => $param_value) {
- if ( !$param_value ) {
- continue;
- }
-
- $param_key = str_replace(' ', '', ucwords(str_replace('_', ' ', $param_name)));
- $param_key[0] = strtolower($param_key[0]);
-
- $oCKeditor->config[$param_key] = $param_value;
- }
-
- $oCKeditor->returnOutput = true;
-
- $events = Array (
- 'configLoaded' => 'function(ev) { CKEDITOR.addCss(ev.editor.config.extraCss); }',
- );
-
- return $oCKeditor->editor($name, $value, Array (), $events);
+ return $this->Field($params);
}
function IsNewItem($params)
{
$object = $this->getObject($params);
return $object->IsNewItem();
}
/**
* Creates link to an item including only it's id
*
* @param Array $params
* @return string
* @access protected
*/
protected function ItemLink($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
if ( !isset($params['pass']) ) {
$params['pass'] = 'm';
}
$params[ $object->getPrefixSpecial() . '_id' ] = $object->GetID();
return $this->Application->ProcessParsedTag('m', 'T', $params);
}
/**
* Creates a button for editing item in Admin Console
*
* @param Array $params
* @return string
* @access protected
* @throws InvalidArgumentException
*/
protected function AdminEditButton($params)
{
if ( EDITING_MODE != EDITING_MODE_CONTENT ) {
return '';
}
$object = $this->getObject($params);
/* @var $object kDBItem */
$item_prefix = isset($params['item_prefix']) ? $params['item_prefix'] : $this->Prefix;
if ( isset($params['template']) ) {
$template = $params['template'];
}
else {
$item_config = $this->Application->getUnitConfig($item_prefix);
$admin_template_prefix = $item_config->getAdminTemplatePrefix();
$template = $item_config->getAdminTemplatePath() . '/' . $admin_template_prefix . 'edit';
if ( !$admin_template_prefix ) {
throw new InvalidArgumentException('Automatic admin editing template detection failed because of missing "AdminTemplatePrefix" unit config option in "' . $this->Prefix . '" unit config');
}
}
$form_name = 'kf_' . str_replace('-', '_', $item_prefix) . '_' . $object->GetID();
$button_icon = isset($params['button_icon']) ? $params['button_icon'] : 'content_mode.png';
$button_class = isset($params['button_class']) ? $params['button_class'] : 'admin-edit-btn';
$button_title = isset($params['button_title']) ? $params['button_title'] : 'la_btn_AdminEditItem';
if ( substr($button_title, 0, 1) == '+' ) {
$button_title = substr($button_title, 1);
}
else {
$button_title = $this->Application->Phrase($button_title, false, true);
}
$icon_url = $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/' . $button_icon;
$button_onclick = '$form_name = ' . json_encode($form_name) . '; std_edit_item(' . json_encode($item_prefix) . ', ' . json_encode($template) . ');';
$button_code = '<button
style="background-image: url(' . $icon_url . ');"
onclick="' . kUtil::escape($button_onclick, kUtil::ESCAPE_HTML) . '"
class="cms-btn-new ' . $button_class . '">' .
kUtil::escape($button_title, kUtil::ESCAPE_HTML) . '
</button>';
if ( !isset($params['pass']) ) {
$params['pass'] = 'm,' . $item_prefix;
}
$params['m_opener'] = 'd';
$params[$item_prefix . '_id'] = $object->GetID();
if ( !isset($params['temp_mode']) || (isset($params['temp_mode']) && $params['temp_mode']) ) {
$params[$item_prefix . '_mode'] = 't';
$params[$item_prefix . '_event'] = 'OnEdit';
}
$params['front'] = 1; // to make opener stack work properly
$params['__URLENCODE__'] = 1; // don't use "&amp;"
$params['__NO_REWRITE__'] = 1; // since admin link
// $params['escape'] = 1; // needed?
unset($params['button_icon'], $params['button_class'], $params['button_title'], $params['template'], $params['item_prefix'], $params['temp_mode']);
// link from Front-End to Admin, don't remove "index.php"
$form_name_escaped = kUtil::escape($form_name, kUtil::ESCAPE_HTML);
$edit_url = kUtil::escape($this->Application->HREF($template, ADMIN_DIRECTORY, $params, 'index.php'), kUtil::ESCAPE_HTML);
$edit_form = '<form method="POST" style="display: inline; margin: 0px" name="' . $form_name_escaped . '" id="' . $form_name_escaped . '" action="' . $edit_url . '"></form>';
if ( isset($params['forms_later']) && $params['forms_later'] ) {
$all_forms = $this->Application->GetVar('all_forms');
$this->Application->SetVar('all_forms', $all_forms . $edit_form);
}
else {
$button_code .= $edit_form;
}
return $button_code;
}
/**
* Calls OnNew event from template, when no other event submitted
*
* @param Array $params
*/
function PresetFormFields($params)
{
$prefix = $this->getPrefixSpecial();
if ( !$this->Application->GetVar($prefix . '_event') ) {
$this->Application->HandleEvent(new kEvent($prefix . ':OnNew'));
}
}
function PrintSerializedFields($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$field = $this->SelectParam($params, 'field');
$data = unserialize($object->GetDBField($field));
$o = '';
$std_params['name'] = $params['render_as'];
$std_params['field'] = $params['field'];
$std_params['pass_params'] = true;
foreach ($data as $key => $row) {
$block_params = array_merge($std_params, $row, array('key'=>$key));
$o .= $this->Application->ParseBlock($block_params);
}
return $o;
}
/**
* Checks if current prefix is main item
*
* @param Array $params
* @return bool
*/
function IsTopmostPrefix($params)
{
return $this->Prefix == $this->Application->GetTopmostPrefix($this->Prefix);
}
function PermSection($params)
{
$section = $this->SelectParam($params, 'section,name');
return $this->getUnitConfig()->getPermSectionByName($section, '');
}
function PerPageSelected($params)
{
$list =& $this->GetList($params);
return $list->GetPerPage(true) == $params['per_page'] ? $params['selected'] : '';
}
/**
* Returns prefix + generated sepcial + any word
*
* @param Array $params
* @return string
*/
function VarName($params)
{
$list =& $this->GetList($params);
return $list->getPrefixSpecial() . '_' . $params['type'];
}
/**
* Returns edit tabs by specified preset name or false in case of error
*
* @param string $preset_name
* @return mixed
*/
function getEditTabs($preset_name)
{
$presets = $this->getUnitConfig()->getEditTabPresets();
if ( !$presets || !isset($presets[$preset_name]) || count($presets[$preset_name]) == 0 ) {
return false;
}
return count($presets[$preset_name]) > 1 ? $presets[$preset_name] : false;
}
/**
* Detects if specified preset has tabs in it
*
* @param Array $params
* @return bool
*/
function HasEditTabs($params)
{
return $this->getEditTabs($params['preset_name']) ? true : false;
}
/**
* Sorts edit tabs based on their priority
*
* @param Array $tab_a
* @param Array $tab_b
* @return int
*/
function sortEditTabs($tab_a, $tab_b)
{
if ($tab_a['priority'] == $tab_b['priority']) {
return 0;
}
return $tab_a['priority'] < $tab_b['priority'] ? -1 : 1;
}
/**
* Prints edit tabs based on preset name specified
*
* @param Array $params
* @return string
* @access protected
*/
protected function PrintEditTabs($params)
{
$edit_tabs = $this->getEditTabs($params['preset_name']);
if ( !$edit_tabs ) {
return '';
}
usort($edit_tabs, Array (&$this, 'sortEditTabs'));
$ret = '';
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
foreach ($edit_tabs as $tab_info) {
$block_params['title'] = $tab_info['title'];
$block_params['template'] = $tab_info['t'];
$ret .= $this->Application->ParseBlock($block_params);
}
return $ret;
}
/**
* Performs image resize to required dimensions and returns resulting url (cached resized image)
*
* @param Array $params
* @return string
*/
function ImageSrc($params)
{
$max_width = isset($params['MaxWidth']) ? $params['MaxWidth'] : false;
$max_height = isset($params['MaxHeight']) ? $params['MaxHeight'] : false;
$logo_filename = isset($params['LogoFilename']) ? $params['LogoFilename'] : false;
$logo_h_margin = isset($params['LogoHMargin']) ? $params['LogoHMargin'] : false;
$logo_v_margin = isset($params['LogoVMargin']) ? $params['LogoVMargin'] : false;
$object = $this->getObject($params);
$field = $this->SelectParam($params, 'name,field');
return $object->GetField($field, 'resize:'.$max_width.'x'.$max_height.';wm:'.$logo_filename.'|'.$logo_h_margin.'|'.$logo_v_margin);
}
/**
* Allows to retrieve given setting from unit config
*
* @param Array $params
* @return mixed
*/
function UnitOption($params)
{
return $this->getUnitConfig()->getSetting($params['name']);
}
/**
* Returns list of allowed toolbar buttons or false, when all is allowed
*
* @param Array $params
* @return string
*/
function VisibleToolbarButtons($params)
{
$preset_name = kUtil::replaceModuleSection($params['title_preset']);
$preset_info = $this->getUnitConfig()->getTitlePresetByName($preset_name);
if ( !$preset_info ) {
trigger_error('Title preset not specified or missing (in tag "<strong>' . $this->getPrefixSpecial() . ':' . __METHOD__ . '</strong>")', E_USER_NOTICE);
return false;
}
if ( !array_key_exists('toolbar_buttons', $preset_info) || !is_array($preset_info['toolbar_buttons']) ) {
return false;
}
// always add search buttons
array_push($preset_info['toolbar_buttons'], 'search', 'search_reset_alt');
$toolbar_buttons = array_values($preset_info['toolbar_buttons']); // reset index
return $toolbar_buttons ? trim(json_encode($toolbar_buttons), '[]') : 'false';
}
/**
* Checks, that "To" part of at least one of range filters is used
*
* @param Array $params
* @return bool
*/
function RangeFiltersUsed($params)
{
$search_helper = $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
return $search_helper->rangeFiltersUsed($this->getPrefixSpecial(), $params['grid']);
}
/**
* This is abstract tag, used to modify unit config data based on template, where it's used.
* Tag is called from "combined_header" block in admin only.
*
* @param Array $params
*/
function ModifyUnitConfig($params)
{
}
/**
* Checks, that field is visible on edit form
*
* @param Array $params
* @return bool
*/
function FieldVisible($params)
{
$check_field = $params['field'];
$field_options = $this->_getFieldDefinition($check_field);
if ( !$field_options ) {
$params['field'] = 'Password';
return $check_field == 'VerifyPassword' ? $this->FieldVisible($params) : true;
}
$show_mode = array_key_exists('show_mode', $field_options) ? $field_options['show_mode'] : true;
if ( $show_mode === smDEBUG ) {
return defined('DEBUG_MODE') && DEBUG_MODE;
}
return $show_mode;
}
/**
* Checks, that there area visible fields in given section on edit form
*
* @param Array $params
* @return bool
*/
function FieldsVisible($params)
{
if ( !$params['fields'] ) {
return true;
}
$check_fields = explode(',', $params['fields']);
foreach ($check_fields as $check_field) {
// when at least one field in subsection is visible, then subsection is visible too
$field_options = $this->_getFieldDefinition($check_field);
if ( $field_options ) {
$show_mode = array_key_exists('show_mode', $field_options) ? $field_options['show_mode'] : true;
}
else {
$show_mode = true;
}
if ( ($show_mode === true) || (($show_mode === smDEBUG) && (defined('DEBUG_MODE') && DEBUG_MODE)) ) {
// field is visible
return true;
}
}
return false;
}
/**
* Returns field definition
*
* @param string $field_name
* @return Array
* @access protected
*/
protected function _getFieldDefinition($field_name)
{
$config = $this->getUnitConfig();
$ret = $config->getFieldByName($field_name);
if ( !$ret ) {
$ret = $config->getVirtualFieldByName($field_name);
}
return $ret;
}
/**
* Checks, that requested option is checked inside field value
*
* @param Array $params
* @return bool
*/
function Selected($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$field = $this->SelectParam($params, 'name,field');
$value = $object->GetDBField($field);
if (strpos($value, '|') !== false) {
$value = explode('|', substr($value, 1, -1));
return in_array($params['value'], $value);
}
return $value;
}
/**
* Displays option name by it's value
*
* @param Array $params
* @return string
* @access protected
*/
protected function OptionValue($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$value = $params['value'];
$field = $this->SelectParam($params, 'name,field');
$field_options = $object->GetFieldOptions($field);
if ( isset($field_options['options'][$value]) ) {
$value = $field_options['options'][$value];
$use_phrases = isset($field_options['use_phrases']) ? $field_options['use_phrases'] : false;
return $use_phrases ? $this->Application->Phrase($value) : $value;
}
return '';
}
/**
* Returns/sets form name for current object
*
* @param Array $params
* @return string
*/
function FormName($params)
{
$form_name = $this->SelectParam($params, 'name,form,form_name');
if ( $form_name ) {
$prefix = $this->getPrefixSpecial();
if ( $this->Application->hasObject( $this->getPrefixSpecial() ) ) {
$object = $this->getObject($params);
/* @var $object kDBItem */
if ( $object->getFormName() != $form_name ) {
trigger_error('Setting form to "<strong>' . $form_name . '</strong>" failed, since object "<strong>' . $this->getPrefixSpecial() . '</strong>" is created before FormName tag (e.g. in event or another tag).', E_USER_WARNING);
}
}
else {
$forms = $this->Application->GetVar('forms', Array ());
$forms[ $this->getPrefixSpecial() ] = $form_name;
$this->Application->SetVar('forms', $forms);
}
return '';
}
$object = $this->getObject($params);
/* @var $object kDBItem */
return $object->getFormName();
}
/**
* Just reloads the object using given parameters
*
* @param Array $params
* @return string
* @access protected
*/
protected function ReloadItem($params)
{
$params['requery'] = 1;
$object = $this->getObject($params);
/* @var $object kDBItem */
return '';
}
-}
+}
\ No newline at end of file
Index: branches/5.3.x/core/units/categories/categories_tag_processor.php
===================================================================
--- branches/5.3.x/core/units/categories/categories_tag_processor.php (revision 15945)
+++ branches/5.3.x/core/units/categories/categories_tag_processor.php (revision 15946)
@@ -1,2263 +1,2287 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class CategoriesTagProcessor extends kDBTagProcessor {
function SubCatCount($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
if ( isset($params['today']) && $params['today'] ) {
$sql = 'SELECT COUNT(*)
FROM ' . $object->TableName . '
WHERE (ParentPath LIKE "' . $object->GetDBField('ParentPath') . '%") AND (CreatedOn > ' . (time() - 86400) . ')';
return $this->Conn->GetOne($sql) - 1;
}
return $object->GetDBField('CachedDescendantCatsQty');
}
/**
* Returns category count in system
*
* @param Array $params
* @return int
*/
function CategoryCount($params)
{
$count_helper = $this->Application->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
$today_only = isset($params['today']) && $params['today'];
return $count_helper->CategoryCount($today_only);
}
function IsNew($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
return $object->GetDBField('IsNew') ? 1 : 0;
}
function IsPick($params)
{
return $this->IsEditorsPick($params);
}
/**
* Returns item's editors pick status (using not formatted value)
*
* @param Array $params
* @return bool
*/
function IsEditorsPick($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
return $object->GetDBField('EditorsPick') == 1;
}
function ItemIcon($params)
{
$grid = $this->getUnitConfig()->getGridByName($params['grid']);
if ( !array_key_exists('Icons', $grid) ) {
return '';
}
$icons = $grid['Icons'];
$icon_prefix = array_key_exists('icon_prefix', $params) ? $params['icon_prefix'] : 'icon16_';
if ( array_key_exists('name', $params) ) {
$icon_name = $params['name'];
return array_key_exists($icon_name, $icons) ? $icons[$icon_name] : '';
}
$object = $this->getObject($params);
/* @var $object kDBList */
if ( $object->GetDBField('ThemeId') > 0 ) {
if ( !$object->GetDBField('IsMenu') ) {
return $icon_prefix . 'section_menuhidden_system.png';
}
return $icon_prefix . 'section_system.png';
}
$status = $object->GetDBField('Status');
if ( $status == STATUS_DISABLED ) {
return $icon_prefix . 'section_disabled.png';
}
if ( !$object->GetDBField('IsMenu') ) {
return $icon_prefix . 'section_menuhidden.png';
}
if ( $status == STATUS_PENDING ) {
return $icon_prefix . 'section_pending.png';
}
if ( $object->GetDBField('IsNew') && ($icon_prefix == 'icon16_') ) {
return $icon_prefix . 'section_new.png'; // show gris icon only in grids
}
return $icon_prefix . 'section.png';
}
function ItemCount($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$ci_table = $this->Application->getUnitConfig('ci')->getTableName();
$module_prefixes = implode(',', $this->Conn->qstrArray($this->_getModulePrefixes()));
$sql = 'SELECT COUNT(*)
FROM ' . $object->TableName . ' c
JOIN ' . $ci_table . ' ci ON c.CategoryId = ci.CategoryId
WHERE (c.TreeLeft BETWEEN ' . $object->GetDBField('TreeLeft') . ' AND ' . $object->GetDBField('TreeRight') . ') AND (ci.ItemPrefix IN (' . $module_prefixes . '))';
return $this->Conn->GetOne($sql);
}
function _getModulePrefixes()
{
$ret = Array ();
foreach ($this->Application->ModuleInfo as $module_info) {
$ret[] = $module_info['Var'];
}
return array_unique($ret);
}
function ListCategories($params)
{
return $this->PrintList2($params);
}
function RootCategoryName($params)
{
return $this->Application->ProcessParsedTag('m', 'RootCategoryName', $params);
}
function CheckModuleRoot($params)
{
$module_name = getArrayValue($params, 'module') ? $params['module'] : 'In-Commerce';
$module_root_cat = $this->Application->findModule('Name', $module_name, 'RootCat');
$additional_cats = $this->SelectParam($params, 'add_cats');
if ($additional_cats) {
$additional_cats = explode(',', $additional_cats);
}
else {
$additional_cats = array();
}
if ($this->Application->GetVar('m_cat_id') == $module_root_cat || in_array($this->Application->GetVar('m_cat_id'), $additional_cats)) {
$home_template = getArrayValue($params, 'home_template');
if ( !$home_template ) {
return;
}
$this->Application->Redirect($home_template, Array('pass'=>'all'));
};
}
function CategoryPath($params)
{
$navigation_bar = $this->Application->recallObject('kNavigationBar');
/* @var $navigation_bar kNavigationBar */
return $navigation_bar->build($params);
}
/**
* Shows category path to specified category
*
* @param Array $params
* @return string
*/
function FieldCategoryPath($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$field = $this->SelectParam($params, 'name,field');
$category_id = $object->GetDBField($field);
if ($category_id) {
$params['cat_id'] = $category_id;
$navigation_bar = $this->Application->recallObject('kNavigationBar');
/* @var $navigation_bar kNavigationBar */
return $navigation_bar->build($params);
}
return '';
}
function CurrentCategoryName($params)
{
$cat_object = $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List');
/* @var $cat_object kDBList */
$sql = 'SELECT '.$this->getTitleField().'
FROM '.$cat_object->TableName.'
WHERE CategoryId = '.(int)$this->Application->GetVar('m_cat_id');
return $this->Conn->GetOne($sql);
}
/**
* Returns current category name
*
* @param Array $params
* @return string
* @todo Find where it's used
*/
function CurrentCategory($params)
{
return $this->CurrentCategoryName($params);
}
function getTitleField()
{
$ml_formatter = $this->Application->recallObject('kMultiLanguage');
/* @var $ml_formatter kMultiLanguage */
return $ml_formatter->LangFieldName('Name');
}
/**
* Returns symlinked category for given category
*
* @param int $category_id
* @return int
*/
function getCategorySymLink($category_id)
{
if (!$category_id) {
// don't bother to get symlink for "Home" category
return $category_id;
}
$cache_key = 'category_symlinks[%CSerial%]';
$cache = $this->Application->getCache($cache_key);
if ($cache === false) {
$config = $this->getUnitConfig();
$id_field = $config->getIDField();
$table_name = $config->getTableName();
// get symlinked categories, that are not yet deleted
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT c1.SymLinkCategoryId, c1.' . $id_field . '
FROM ' . $table_name . ' c1
JOIN ' . $table_name . ' c2 ON c1.SymLinkCategoryId = c2.' . $id_field;
$cache = $this->Conn->GetCol($sql, $id_field);
$this->Application->setCache($cache_key, $cache);
}
return array_key_exists($category_id, $cache) ? $cache[$category_id] : $category_id;
}
function CategoryLink($params)
{
$category_id = getArrayValue($params, 'cat_id');
if ( $category_id === false ) {
$category_id = $this->Application->GetVar($this->getPrefixSpecial() . '_id');
}
if ( "$category_id" == 'Root' ) {
$category_id = $this->Application->findModule('Name', $params['module'], 'RootCat');
}
elseif ( "$category_id" == 'current' ) {
$category_id = $this->Application->GetVar('m_cat_id');
}
if ( !array_key_exists('direct_link', $params) || !$params['direct_link'] ) {
$category_id = $this->getCategorySymLink((int)$category_id);
}
else {
unset($params['direct_link']);
}
$virtual_template = $this->Application->getVirtualPageTemplate($category_id);
if ( ($virtual_template !== false) && preg_match('/external:(.*)/', $virtual_template, $rets) ) {
// external url (return here, instead of always replacing $params['t'] for kApplication::HREF to find it)
return $rets[1];
}
unset($params['cat_id'], $params['module']);
$new_params = Array ('pass' => 'm', 'm_cat_id' => $category_id, 'pass_category' => 1);
$params = array_merge($params, $new_params);
return $this->Application->ProcessParsedTag('m', 't', $params);
}
function CategoryList($params)
{
//$object = $this->Application->recallObject( $this->getPrefixSpecial() , $this->Prefix.'_List', $params );
$object =& $this->GetList($params);
if ($object->GetRecordsCount() == 0)
{
if (isset($params['block_no_cats'])) {
$params['name'] = $params['block_no_cats'];
return $this->Application->ParseBlock($params);
}
else {
return '';
}
}
if (isset($params['block'])) {
return $this->PrintList($params);
}
else {
$params['block'] = $params['block_main'];
if (isset($params['block_row_start'])) {
$params['row_start_block'] = $params['block_row_start'];
}
if (isset($params['block_row_end'])) {
$params['row_end_block'] = $params['block_row_end'];
}
return $this->PrintList2($params);
}
}
function Meta($params)
{
$object = $this->Application->recallObject($this->Prefix); // .'.-item'
/* @var $object CategoriesItem */
$meta_type = $params['name'];
if ($object->isLoaded()) {
// 1. get module prefix by current category
$category_helper = $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$category_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1));
$module_info = $category_helper->getCategoryModule($params, $category_path);
// In-Edit & Proj-CMS module prefixes doesn't have custom field with item template
if ($module_info && $module_info['Var'] != 'adm' && $module_info['Var'] != 'st') {
// 2. get item template by current category & module prefix
$rewrite_processor = $this->Application->recallObject('kRewriteUrlProcessor');
/* @var $rewrite_processor kRewriteUrlProcessor */
$category_params = Array (
'CategoryId' => $object->GetID(),
'ParentPath' => $object->GetDBField('ParentPath'),
);
$item_template = $rewrite_processor->GetItemTemplate($category_params, $module_info['Var']);
if ($this->Application->GetVar('t') == $item_template) {
// we are located on item's details page
$item = $this->Application->recallObject($module_info['Var']);
/* @var $item kCatDBItem */
// 3. get item's meta data
$value = $item->GetField('Meta'.$meta_type);
if ($value) {
return $value;
}
}
// 4. get category meta data
$value = $object->GetField('Meta'.$meta_type);
if ($value) {
return $value;
}
}
}
// 5. get default meta data
switch ($meta_type) {
case 'Description':
$config_name = 'Category_MetaDesc';
break;
case 'Keywords':
$config_name = 'Category_MetaKey';
break;
}
return $this->Application->ConfigValue($config_name);
}
function BuildListSpecial($params)
{
if (($this->Special != '') && !is_numeric($this->Special)) {
// When recursive category list is printed (like in sitemap), then special
// should be generated even if it's already present. Without it list on this
// level will erase list on previous level, because it will be stored in same object.
return $this->Special;
}
if ( isset($params['parent_cat_id']) ) {
$parent_cat_id = $params['parent_cat_id'];
}
else {
$parent_cat_id = $this->Application->GetVar($this->Prefix.'_id');
if (!$parent_cat_id) {
$parent_cat_id = $this->Application->GetVar('m_cat_id');
}
if (!$parent_cat_id) {
$parent_cat_id = 0;
}
}
$list_unique_key = $this->getUniqueListKey($params);
// check for "admin" variable, because we are parsing front-end template from admin when using template editor feature
if ($this->Application->GetVar('admin') || !$this->Application->isAdmin) {
// add parent category to special, when on Front-End,
// because there can be many category lists on same page
$list_unique_key .= $parent_cat_id;
}
if ($list_unique_key == '') {
return parent::BuildListSpecial($params);
}
return crc32($list_unique_key);
}
function IsCurrent($params)
{
$object = $this->getObject($params);
if ($object->GetID() == $this->Application->GetVar('m_cat_id')) {
return true;
}
else {
return false;
}
}
/**
* Substitutes category in last template base on current category
* This is required becasue when you navigate catalog using AJAX, last_template is not updated
* but when you open item edit from catalog last_template is used to build opener_stack
* So, if we don't substitute m_cat_id in last_template, after saving item we'll get redirected
* to the first category we've opened, not the one we navigated to using AJAX
*
* @param Array $params
*/
function UpdateLastTemplate($params)
{
$category_id = $this->Application->GetVar('m_cat_id');
$wid = $this->Application->GetVar('m_wid');
list($index_file, $env) = explode('|', $this->Application->RecallVar(rtrim('last_template_'.$wid, '_')), 2);
$vars_backup = Array ();
$vars = $this->Application->processQueryString( str_replace('%5C', '\\', $env) );
foreach ($vars as $var_name => $var_value) {
$vars_backup[$var_name] = $this->Application->GetVar($var_name);
$this->Application->SetVar($var_name, $var_value);
}
// update required fields
$this->Application->SetVar('m_cat_id', $category_id);
$this->Application->Session->SaveLastTemplate($params['template']);
foreach ($vars_backup as $var_name => $var_value) {
$this->Application->SetVar($var_name, $var_value);
}
}
function GetParentCategory($params)
{
$parent_id = $this->Application->getBaseCategory();
$category_id = $this->Application->GetVar('m_cat_id');
if ($category_id != $parent_id) {
$config = $this->getUnitConfig();
$sql = 'SELECT ParentId
FROM ' . $config->getTableName() . '
WHERE ' . $config->getIDField() . ' = ' . $category_id;
$parent_id = $this->Conn->GetOne($sql);
}
return $parent_id;
}
function InitCacheUpdater($params)
{
kUtil::safeDefine('CACHE_PERM_CHUNK_SIZE', 30);
$continue = $this->Application->GetVar('continue');
$total_cats = (int)$this->Conn->GetOne('SELECT COUNT(*) FROM ' . TABLE_PREFIX . 'Categories');
if ( $continue === false ) {
$rebuild_mode = $this->Application->ConfigValue('CategoryPermissionRebuildMode');
if ( $rebuild_mode == CategoryPermissionRebuild::AUTOMATIC && $total_cats > CACHE_PERM_CHUNK_SIZE ) {
// first step, if category count > CACHE_PERM_CHUNK_SIZE, then ask for cache update
return true;
}
// if we don't have to ask, then assume user selected "Yes" in permcache update dialog
$continue = 1;
}
$updater = $this->Application->makeClass('kPermCacheUpdater', Array ($continue));
/* @var $updater kPermCacheUpdater */
if ( $continue === '0' ) { // No in dialog
$updater->clearData();
$this->Application->Redirect($params['destination_template']);
}
$ret = false; // don't ask for update
if ( $continue == 1 ) { // Initial run
$updater->setData();
}
if ( $continue == 2 ) { // Continuing
// called from AJAX request => returns percent
$needs_more = true;
while ( $needs_more && $updater->iteration <= CACHE_PERM_CHUNK_SIZE ) {
// until proceeded in this step category count exceeds category per step limit
$needs_more = $updater->DoTheJob();
}
if ( $needs_more ) {
// still some categories are left for next step
$updater->setData();
}
else {
// all done, update left tree and redirect
$updater->SaveData();
$this->Application->HandleEvent(new kEvent('c:OnResetCMSMenuCache'));
$this->Application->RemoveVar('PermCache_UpdateRequired');
$this->Application->StoreVar('RefreshStructureTree', 1);
$this->Application->Redirect($params['destination_template']);
}
$ret = $updater->getDonePercent();
}
return $ret;
}
/**
* Parses warning block, but with style="display: none;". Used during permissions saving from AJAX
*
* @param Array $params
* @return string
* @access protected
*/
protected function SaveWarning($params)
{
if ( $this->Prefix == 'st' ) {
// don't use this method for other prefixes then Categories, that use this tag processor
return parent::SaveWarning($params);
}
$main_prefix = getArrayValue($params, 'main_prefix');
if ( $main_prefix && $main_prefix != '$main_prefix' ) {
$top_prefix = $main_prefix;
}
else {
$top_prefix = $this->Application->GetTopmostPrefix($this->Prefix);
}
$temp_tables = substr($this->Application->GetVar($top_prefix . '_mode'), 0, 1) == 't';
$modified = $this->Application->RecallVar($top_prefix . '_modified');
if ( !$temp_tables ) {
$this->Application->RemoveVar($top_prefix . '_modified');
return '';
}
$block_name = $this->SelectParam($params, 'render_as,name');
if ( $block_name ) {
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $block_name;
$block_params['edit_mode'] = $temp_tables ? 1 : 0;
$block_params['display'] = $temp_tables && $modified ? 1 : 0;
return $this->Application->ParseBlock($block_params);
}
return $temp_tables && $modified ? 1 : 0;
}
/**
* Allows to detect if this prefix has something in clipboard
*
* @param Array $params
* @return bool
*/
function HasClipboard($params)
{
$clipboard = $this->Application->RecallVar('clipboard');
if ($clipboard) {
$clipboard = unserialize($clipboard);
foreach ($clipboard as $prefix => $clipboard_data) {
foreach ($clipboard_data as $mode => $ids) {
if ( count($ids) ) {
return 1;
}
}
}
}
return 0;
}
/**
* Allows to detect if root category being edited
*
* @param Array $params
*/
function IsRootCategory($params)
{
$object = $this->getObject($params);
/* @var $object CategoriesItem */
return $object->IsRoot();
}
/**
* Returns home category id
*
* @param Array $params
* @return int
*/
function HomeCategory($params)
{
return $this->Application->getBaseCategory();
}
/**
* Used for disabling "Home" and "Up" buttons in category list
*
* @param Array $params
* @return bool
*/
function ModuleRootCategory($params)
{
return $this->Application->GetVar('m_cat_id') == $this->Application->getBaseCategory();
}
function CatalogItemCount($params)
{
$params['skip_quering'] = true;
$object =& $this->GetList($params);
return $object->GetRecordsCount(false) != $object->GetRecordsCount() ? $object->GetRecordsCount().' / '.$object->GetRecordsCount(false) : $object->GetRecordsCount();
}
function InitCatalog($params)
{
$tab_prefixes = $this->Application->GetVar('tp'); // {all, <prefixes_list>, none}
if ( $tab_prefixes === false ) {
$tab_prefixes = 'all';
}
$skip_prefixes = isset($params['skip_prefixes']) && $params['skip_prefixes'] ? explode(',', $params['skip_prefixes']) : Array();
$replace_main = isset($params['replace_m']) && $params['replace_m'];
// get all prefixes available
$prefixes = Array();
foreach ($this->Application->ModuleInfo as $module_name => $module_data) {
$prefix = $module_data['Var'];
if ( $prefix == 'adm' /* || $prefix == 'm'*/ ) {
continue;
}
if ($prefix == 'm' && $replace_main) {
$prefix = 'c';
}
$prefixes[] = $prefix;
}
if ($tab_prefixes == 'none') {
$skip_prefixes = array_unique(array_merge($skip_prefixes, $prefixes));
unset($skip_prefixes[ array_search($replace_main ? 'c' : 'm', $skip_prefixes) ]);
}
elseif ($tab_prefixes != 'all') {
// prefix list here
$tab_prefixes = explode(',', $tab_prefixes); // list of prefixes that should stay
$skip_prefixes = array_unique(array_merge($skip_prefixes, array_diff($prefixes, $tab_prefixes)));
}
$params['name'] = $params['render_as'];
$params['skip_prefixes'] = implode(',', $skip_prefixes);
return $this->Application->ParseBlock($params);
}
/**
* Determines, that printed category/menu item is currently active (will also match parent category)
*
* @param Array $params
* @return bool
*/
function IsActive($params)
{
static $current_path = null;
if ( !isset($current_path) ) {
$sql = 'SELECT ParentPath
FROM ' . TABLE_PREFIX . 'Categories
WHERE CategoryId = ' . (int)$this->Application->GetVar('m_cat_id');
$current_path = $this->Conn->GetOne($sql);
}
if ( array_key_exists('parent_path', $params) ) {
$test_path = $params['parent_path'];
}
else {
$template = isset($params['template']) ? $params['template'] : '';
if ( $template ) {
// when using from "c:CachedMenu" tag
$sql = 'SELECT ParentPath
FROM ' . TABLE_PREFIX . 'Categories
WHERE NamedParentPath = ' . $this->Conn->qstr('Content/' . $template);
$test_path = $this->Conn->GetOne($sql);
}
else {
// when using from "c:PrintList" tag
$cat_id = array_key_exists('cat_id', $params) && $params['cat_id'] ? $params['cat_id'] : false;
if ( $cat_id === false ) {
// category not supplied -> get current from PrintList
$category = $this->getObject($params);
}
else {
if ( "$cat_id" == 'Root' ) {
$cat_id = $this->Application->findModule('Name', $params['module'], 'RootCat');
}
$category = $this->Application->recallObject($this->Prefix . '.-c' . $cat_id, $this->Prefix, Array ('skip_autoload' => true));
/* @var $category CategoriesItem */
$category->Load($cat_id);
}
$test_path = $category->GetDBField('ParentPath');
}
}
return strpos($current_path, $test_path) !== false;
}
/**
* Checks if user have one of required permissions
*
* @param Array $params
* @return bool
*/
function HasPermission($params)
{
$perm_helper = $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$params['raise_warnings'] = 0;
$object = $this->getObject($params);
/* @var $object kDBItem */
$params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id');
return $perm_helper->TagPermissionCheck($params);
}
/**
* Prepares name for field with event in it (used only on front-end)
*
* @param Array $params
* @return string
*/
function SubmitName($params)
{
return 'events[' . $this->Prefix . '][' . $params['event'] . ']';
}
/**
* Returns last modification date of items in category / system
*
* @param Array $params
* @return string
*/
function LastUpdated($params)
{
$category_id = (int)$this->Application->GetVar('m_cat_id');
$local = array_key_exists('local', $params) && ($category_id > 0) ? $params['local'] : false;
$serial_name = $this->Application->incrementCacheSerial('c', $local ? $category_id : null, false);
$cache_key = 'category_last_updated[%' . $serial_name . '%]';
$row_data = $this->Application->getCache($cache_key);
if ( $row_data === false ) {
if ( $local && ($category_id > 0) ) {
// scan only current category & it's children
list ($tree_left, $tree_right) = $this->Application->getTreeIndex($category_id);
$sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
FROM ' . TABLE_PREFIX . 'Categories
WHERE TreeLeft BETWEEN ' . $tree_left . ' AND ' . $tree_right;
}
else {
// scan all categories in system
$sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
FROM ' . TABLE_PREFIX . 'Categories';
}
$this->Conn->nextQueryCachable = true;
$row_data = $this->Conn->GetRow($sql);
$this->Application->setCache($cache_key, $row_data);
}
if ( !$row_data ) {
return '';
}
$date = $row_data[$row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate'];
// format date
$format = isset($params['format']) ? $params['format'] : '_regional_DateTimeFormat';
if ( preg_match("/_regional_(.*)/", $format, $regs) ) {
$lang = $this->Application->recallObject('lang.current');
/* @var $lang LanguagesItem */
if ( $regs[1] == 'DateTimeFormat' ) {
// combined format
$format = $lang->GetDBField('DateFormat') . ' ' . $lang->GetDBField('TimeFormat');
}
else {
// simple format
$format = $lang->GetDBField($regs[1]);
}
}
return date($format, $date);
}
function CategoryItemCount($params)
{
$object = $this->getObject($params);
/* @var $object kDBList */
$params['cat_id'] = $object->GetID();
$count_helper = $this->Application->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
return $count_helper->CategoryItemCount($params['prefix'], $params);
}
/**
* Returns prefix + any word (used for shared between categories per page settings)
*
* @param Array $params
* @return string
*/
function VarName($params)
{
return $this->Prefix.'_'.$params['type'];
}
/**
* Checks if current category is valid symbolic link to another category
*
* @param Array $params
* @return string
*/
function IsCategorySymLink($params)
{
$object = $this->getObject($params);
/* @var $object kDBList */
$sym_category_id = $object->GetDBField('SymLinkCategoryId');
if ( is_null($sym_category_id) ) {
return false;
}
$config = $this->getUnitConfig();
$id_field = $config->getIDField();
$table_name = $config->getTableName();
$sql = 'SELECT ' . $id_field . '
FROM ' . $table_name . '
WHERE ' . $id_field . ' = ' . $sym_category_id;
return $this->Conn->GetOne($sql) ? true : false;
}
/**
* Returns module prefix based on root category for given
*
* @param Array $params
* @return string
*/
function GetModulePrefix($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$parent_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1));
$category_helper = $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$module_info = $category_helper->getCategoryModule($params, $parent_path);
return $module_info['Var'];
}
function ImageSrc($params)
{
list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial());
return $tag_processed ? $ret : false;
}
function PageLink($params)
{
$params['m_cat_page'] = $this->Application->GetVar($this->getPrefixSpecial() . '_Page');
return parent::PageLink($params);
}
/**
* Returns spelling suggestions against search keyword
*
* @param Array $params
* @return string
* @access protected
*/
protected function SpellingSuggestions($params)
{
$keywords = htmlspecialchars_decode(trim($this->Application->GetVar('keywords')));
if ( !$keywords ) {
return '';
}
// 1. try to get already cached suggestion
$cache_key = 'search.suggestion[%SpellingDictionarySerial%]:' . $keywords;
$suggestion = $this->Application->getCache($cache_key);
if ( $suggestion !== false ) {
return $suggestion;
}
$table_name = $this->Application->getUnitConfig('spelling-dictionary')->getTableName();
// 2. search suggestion in database
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT SuggestedCorrection
FROM ' . $table_name . '
WHERE MisspelledWord = ' . $this->Conn->qstr($keywords);
$suggestion = $this->Conn->GetOne($sql);
if ( $suggestion !== false ) {
$this->Application->setCache($cache_key, $suggestion);
return $suggestion;
}
// 3. suggestion not found in database, ask webservice
$app_id = $this->Application->ConfigValue('YahooApplicationId');
$url = 'http://search.yahooapis.com/WebSearchService/V1/spellingSuggestion?appid=' . $app_id . '&query=';
$curl_helper = $this->Application->recallObject('CurlHelper');
/* @var $curl_helper kCurlHelper */
$xml_data = $curl_helper->Send( $url . kUtil::escape($keywords, kUtil::ESCAPE_URL) );
$xml_helper = $this->Application->recallObject('kXMLHelper');
/* @var $xml_helper kXMLHelper */
$root_node =& $xml_helper->Parse($xml_data);
/* @var $root_node kXMLNode */
$result = $root_node->FindChild('RESULT');
/* @var $result kXMLNode */
if ( is_object($result) ) {
// webservice responded -> save in local database
$fields_hash = Array ('MisspelledWord' => $keywords, 'SuggestedCorrection' => $result->Data);
$this->Conn->doInsert($fields_hash, $table_name);
$this->Application->setCache($cache_key, $result->Data);
return $result->Data;
}
return '';
}
/**
* Shows link for searching by suggested word
*
* @param Array $params
* @return string
*/
function SuggestionLink($params)
{
$params['keywords'] = $this->SpellingSuggestions($params);
return $this->Application->ProcessParsedTag('m', 'Link', $params);
}
function InitCatalogTab($params)
{
$tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible
$tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab
$tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid
// set default params (same as in catalog)
if ( $tab_params['mode'] === false ) {
$tab_params['mode'] = 'multi';
}
if ( $tab_params['special'] === false ) {
$tab_params['special'] = '';
}
if ( $tab_params['dependant'] === false ) {
$tab_params['dependant'] = 'yes';
}
// pass params to block with tab content
$params['name'] = $params['render_as'];
$special = $tab_params['special'] ? $tab_params['special'] : $this->Special;
$params['prefix'] = trim($this->Prefix.'.'.$special, '.');
$prefix_append = $this->Application->GetVar('prefix_append');
if ($prefix_append) {
$params['prefix'] .= $prefix_append;
}
$default_grid = array_key_exists('default_grid', $params) ? $params['default_grid'] : 'Default';
$radio_grid = array_key_exists('radio_grid', $params) ? $params['radio_grid'] : 'Radio';
$params['cat_prefix'] = trim('c.'.($tab_params['special'] ? $tab_params['special'] : $this->Special), '.');
$params['tab_mode'] = $tab_params['mode'];
$params['grid_name'] = ($tab_params['mode'] == 'multi') ? $default_grid : $radio_grid;
$params['tab_dependant'] = $tab_params['dependant'];
$params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name
if ($special == 'showall' || $special == 'user') {
$params['grid_name'] .= 'ShowAll';
}
// use $pass_params to be able to pass 'tab_init' parameter from m_ModuleInclude tag
return $this->Application->ParseBlock($params, 1);
}
/**
* Show CachedNavbar of current item primary category
*
* @param Array $params
* @return string
*/
function CategoryName($params)
{
// show category cachednavbar of
$object = $this->getObject($params);
/* @var $object kDBItem */
$category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId');
$cache_key = 'category_paths[%CIDSerial:' . $category_id . '%][%PhrasesSerial%][Adm:' . (int)$this->Application->isAdmin . ']';
$category_path = $this->Application->getCache($cache_key);
if ($category_path === false) {
// not chached
if ($category_id > 0) {
$cached_navbar = $object->GetField('CachedNavbar');
if ($category_id == $object->GetDBField('ParentId')) {
// parent category cached navbar is one element smaller, then current ones
$cached_navbar = explode('&|&', $cached_navbar);
array_pop($cached_navbar);
$cached_navbar = implode('&|&', $cached_navbar);
}
else {
// no relation with current category object -> query from db
$language_id = (int)$this->Application->GetVar('m_lang');
if (!$language_id) {
$language_id = 1;
}
$sql = 'SELECT l' . $language_id . '_CachedNavbar
FROM ' . $object->TableName . '
WHERE ' . $object->IDField . ' = ' . $category_id;
$cached_navbar = $this->Conn->GetOne($sql);
}
$cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $cached_navbar);
$category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > ');
}
else {
$category_path = $this->Application->Phrase(($this->Application->isAdmin ? 'la_' : 'lu_') . 'rootcategory_name');
}
$this->Application->setCache($cache_key, $category_path);
}
return $category_path;
}
// structure related
/**
* Returns page object based on requested params
*
* @param Array $params
* @return CategoriesItem
*/
function &_getPage($params)
{
$page = $this->Application->recallObject($this->Prefix . '.' . $this->_getPageSpecial($params), null, $params);
/* @var $page kDBItem */
// 1. load by given id
$page_id = array_key_exists('page_id', $params) ? $params['page_id'] : 0;
if ( $page_id ) {
if ( $page_id != $page->GetID() ) {
// load if different
$page->Load($page_id);
}
return $page;
}
// 2. load by template
$template = array_key_exists('page', $params) ? $params['page'] : '';
if ( !$template ) {
$template = $this->Application->GetVar('t');
}
// different path in structure AND design template differs from requested template
$structure_path_match = mb_strtolower($page->GetDBField('NamedParentPath')) == mb_strtolower('Content/' . $template);
$design_match = $page->GetDBField('CachedTemplate') == $template;
if ( !$structure_path_match && !$design_match ) {
// Same sql like in "c:getPassedID". Load, when current page object doesn't match requested page object
$themes_helper = $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$page_id = $themes_helper->getPageByTemplate($template);
$page->Load($page_id);
}
return $page;
}
/**
* Returns unique special for each used page
*
* @param Array $params
* @return string
* @access protected
*/
protected function _getPageSpecial($params)
{
$ret = Array ();
$page_id = array_key_exists('page_id', $params) ? $params['page_id'] : 0;
$template = array_key_exists('page', $params) ? $params['page'] : '';
if ( $page_id ) {
$ret[] = 'page_id=' . $page_id;
}
if ( $template ) {
$ret[] = 'page=' . $template;
}
return $ret ? '-virtual-' . kUtil::crc32(serialize($ret)) : '-virtual';
}
/**
* Returns requested content block content of current or specified page
*
* @param Array $params
* @return string
*/
function ContentBlock($params)
{
$num = getArrayValue($params, 'num');
if ( !$num ) {
$name = getArrayValue($params, 'name');
if ( $name ) {
$num = kUtil::crc32($name);
}
}
if ( !$num ) {
return 'NO CONTENT NUM SPECIFIED';
}
$page =& $this->_getPage($params);
/* @var $page kDBItem */
if ( !$page->isLoaded() ) {
// page is not created yet => all blocks are empty
return '';
}
$page_helper = $this->Application->recallObject('PageHelper');
/* @var $page_helper PageHelper */
$content = $this->Application->recallObject('content.-block', null, Array ('skip_autoload' => true));
/* @var $content kDBItem */
if ( !$page_helper->loadContentBlock($content, $page, $num) && EDITING_MODE ) {
$page_helper->createNewContentBlock($page->GetID(), $num);
$page_helper->loadContentBlock($content, $page, $num);
}
$edit_code_before = $edit_code_after = '';
+ $inline_editing = isset($params['mode']) && $params['mode'] == 'inline';
if ( EDITING_MODE == EDITING_MODE_CONTENT ) {
- $button_code = $this->Application->ProcessParsedTag($content->getPrefixSpecial(), 'AdminEditButton', $params);
+ if ( $inline_editing ) {
+ $params['name'] = 'content_block_' . $num;
- $edit_code_before = '
- <div class="cms-edit-btn-container">
- ' . $button_code . '
- <div class="cms-btn-content">';
+ $editing_hint = $this->Application->Phrase('la_hint_ClickToEdit', false, true);
- $edit_code_after = '</div></div>';
+ $edit_code_before = '
+ <div class="cms-edit-btn-container mode-inline-edit" data-content-id="' . $content->GetID() . '">
+ <div class="inline-edit-layer"></div>
+ <div class="inline-saving-layer"></div>
+ <div class="cms-btn-content" title="' . kUtil::escape($editing_hint, kUtil::ESCAPE_HTML) . '" contenteditable="true" id="' . kUtil::escape('content_block_' . $num, kUtil::ESCAPE_HTML) . '">';
+
+ $edit_code_after = '</div></div>' . $this->FCKEditor($params);
+ }
+ else {
+ $button_code = $this->Application->ProcessParsedTag($content->getPrefixSpecial(), 'AdminEditButton', $params);
+
+ $edit_code_before = '
+ <div class="cms-edit-btn-container">
+ ' . $button_code . '
+ <div class="cms-btn-content">';
+
+ $edit_code_after = '</div></div>';
+ }
}
if ( $this->Application->GetVar('_editor_preview_') == 1 ) {
$data = $this->Application->RecallVar('_editor_preview_content_');
}
+ elseif ( EDITING_MODE == EDITING_MODE_CONTENT && $inline_editing ) {
+ // don't use formatter, that replaced "@@ID@@" links
+ $content->SetFieldOption('Content', 'using_fck', false);
+ $data = $content->GetField('Content');
+ $content->SetFieldOption('Content', 'using_fck', true);
+ }
else {
+ // use formatter, that replaced "@@ID@@" links
$data = $content->GetField('Content');
}
$data = $edit_code_before . $this->_transformContentBlockData($data, $params) . $edit_code_after;
if ( $data != '' ) {
$this->Application->Parser->DataExists = true;
}
return $data;
}
/**
* Apply all kinds of content block data transformations without rewriting ContentBlock tag
*
* @param string $data
* @param Array $params
* @return string
*/
function _transformContentBlockData(&$data, $params)
{
return $data;
}
/**
* Returns current page name or page based on page/page_id parameters
*
* @param Array $params
* @return string
* @todo Used?
*/
function PageName($params)
{
$page =& $this->_getPage($params);
return $page->GetDBField('Name');
}
/**
* Returns current/given page information
*
* @param Array $params
* @return string
*/
function PageInfo($params)
{
$page =& $this->_getPage($params);
switch ($params['type']) {
case 'title':
// TODO: rename column to SectionTitle
$db_field = 'Name'; // "Section Title" - title to show on page (e.g. in <h1> tag)
break;
case 'htmlhead_title':
// TODO: rename column to HtmlTitle
$db_field = 'Title'; // "Title (on Page)" - in <title> html tag
break;
case 'meta_title':
$db_field = 'MetaTitle';
break;
case 'menu_title':
$db_field = 'MenuTitle'; // "Title (Menu Item)" - in menu and navigation bar
break;
case 'meta_keywords':
$db_field = 'MetaKeywords';
$cat_field = 'Keywords';
break;
case 'meta_description':
$db_field = 'MetaDescription';
$cat_field = 'Description';
break;
case 'tracking':
case 'index_tools':
if (!EDITING_MODE) {
$tracking = $page->GetDBField('IndexTools');
return $tracking ? $tracking : $this->Application->ConfigValue('cms_DefaultTrackingCode');
}
// no break here on purpose
default:
return '';
}
$default = isset($params['default']) ? $params['default'] : '';
$val = $page->GetField($db_field);
if (!$default) {
if ($this->Application->isModuleEnabled('In-Portal')) {
if (!$val && ($params['type'] == 'meta_keywords' || $params['type'] == 'meta_description')) {
// take category meta if it's not set for the page
return $this->Application->ProcessParsedTag('c', 'Meta', Array('name' => $cat_field));
}
}
}
if (isset($params['force_default']) && $params['force_default']) {
return $default;
}
if (preg_match('/^_Auto:/', $val)) {
$val = $default;
/*if ($db_field == 'Title') {
$page->SetDBField($db_field, $default);
$page->Update();
}*/
}
elseif ($page->GetID() == false) {
return $default;
}
return $val;
}
/**
* Includes admin css and js, that are required for cms usage on Front-Edn
*
* @param Array $params
* @return string
* @access protected
*/
protected function EditingScripts($params)
{
if ( $this->Application->GetVar('admin_scripts_included') || !EDITING_MODE ) {
return '';
}
$this->Application->SetVar('admin_scripts_included', 1);
$js_url = $this->Application->BaseURL() . 'core/admin_templates/js';
$minify_helper = $this->Application->recallObject('MinifyHelper');
/* @var $minify_helper MinifyHelper */
$to_compress = Array (
$js_url . '/jquery/thickbox/thickbox.css',
$js_url . '/../incs/cms.css',
$js_url . '/../img/toolbar/toolbar-sprite.css',
);
$css_compressed = $minify_helper->CompressScriptTag(Array ('files' => implode('|', $to_compress), 'templates_base' => $js_url . '/../'));
$ret = '<link rel="stylesheet" href="' . $css_compressed . '" type="text/css" media="screen"/>' . "\n";
$ret .= ' <!--[if IE]>
<link rel="stylesheet" href="' . $js_url . '/../incs/cms_ie.css' . '" type="text/css" media="screen"/>
<![endif]-->';
if ( EDITING_MODE == EDITING_MODE_DESIGN ) {
$ret .= ' <style type="text/css" media="all">
div.movable-element .movable-header { cursor: move; }
</style>';
}
$ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery-1.9.1.min.js"></script>' . "\n";
$ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery-ui-1.10.3.custom.min.js"></script>' . "\n";
$to_compress = Array (
$js_url . '/is.js',
$js_url . '/application.js',
$js_url . '/script.js',
$js_url . '/toolbar.js',
$js_url . '/jquery/thickbox/thickbox.js',
$js_url . '/template_manager.js',
);
$js_compressed = $minify_helper->CompressScriptTag( Array ('files' => implode('|', $to_compress)) );
$ret .= '<script type="text/javascript" src="' . $js_compressed . '"></script>' . "\n";
$ret .= '<script language="javascript">' . "\n";
$ret .= "TB.pathToImage = '" . $js_url . "/jquery/thickbox/loadingAnimation.gif';" . "\n";
$template = $this->Application->GetVar('t');
$theme_id = $this->Application->GetVar('m_theme');
$url_params = Array ('block' => '#BLOCK#', 'theme-file_event' => '#EVENT#', 'theme_id' => $theme_id, 'source' => $template, 'pass' => 'all,theme-file', 'front' => 1, 'm_opener' => 'd', '__NO_REWRITE__' => 1, 'no_amp' => 1);
$edit_template_url = $this->Application->HREF('themes/template_edit', ADMIN_DIRECTORY, $url_params, 'index.php');
$url_params = Array ('theme-file_event' => 'OnSaveLayout', 'source' => $template, 'pass' => 'all,theme-file', '__NO_REWRITE__' => 1, 'no_amp' => 1);
$save_layout_url = $this->Application->HREF('index', '', $url_params);
+ $url_params = Array ('content_event' => 'OnSaveContentBlock', 'pass' => 'all,content', '__NO_REWRITE__' => 1, 'no_amp' => 1);
+ $save_content_url = $this->Application->HREF('index', ADMIN_DIRECTORY, $url_params, 'index.php');
+
$page =& $this->_getPage($params);
$page_helper = $this->Application->recallObject('PageHelper');
/* @var $page_helper PageHelper */
$class_params = Array (
+ 'languagePrefix' => 'l' . $this->Application->GetVar('m_lang') . '_',
'pageId' => $page->GetID(),
'pageInfo' => $page->isLoaded() ? $page_helper->getPageInfo( $page->GetID() ) : Array (),
'editUrl' => $edit_template_url,
'browseUrl' => $this->Application->HREF('', '', Array ('editing_mode' => '#EDITING_MODE#', '__NO_REWRITE__' => 1, 'no_amp' => 1)),
'saveLayoutUrl' => $save_layout_url,
+ 'saveContentUrl' => $save_content_url,
'editingMode' => (int)EDITING_MODE,
);
$site_name = strip_tags($this->Application->ConfigValue('Site_Name'));
$ret .= "var aTemplateManager = new TemplateManager(" . json_encode($class_params) . ");\n";
$ret .= "var main_title = '" . kUtil::escape($site_name, kUtil::ESCAPE_JS) . "';" . "\n";
$use_popups = (int)$this->Application->ConfigValue('UsePopups');
$ret .= "var \$use_popups = " . ($use_popups > 0 ? 'true' : 'false') . ";\n";
$ret .= "var \$modal_windows = " . ($use_popups == 2 ? 'true' : 'false') . ";\n";
if ( EDITING_MODE != EDITING_MODE_BROWSE ) {
$ret .= 'var $visible_toolbar_buttons = true' . ";\n";
$ret .= 'var $use_toolbarlabels = ' . ($this->Application->ConfigValue('UseToolbarLabels') ? 'true' : 'false') . ";\n";;
$ret .= "var base_url = '" . $this->Application->BaseURL() . "';" . "\n";
$ret .= 'TB.closeHtml = \'<img src="' . $js_url . '/../img/close_window15.gif" width="15" height="15" style="border-width: 0px;" alt="close"/><br/>\';' . "\n";
$url_params = Array ('m_theme' => '', 'pass' => 'm', 'm_opener' => 'r', '__NO_REWRITE__' => 1, 'no_amp' => 1);
$browse_url = $this->Application->HREF('catalog/catalog', ADMIN_DIRECTORY, $url_params, 'index.php');
$browse_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $browse_url);
$admin_title = strip_tags($this->Application->Phrase('la_AdministrativeConsole', false));
$ret .= '
set_window_title(document.title + \' - ' . kUtil::escape($admin_title, kUtil::ESCAPE_JS) . '\');
t = \'' . $this->Application->GetVar('t') . '\';
if (window.parent.frames["menu"] != undefined) {
if ( $.isFunction(window.parent.frames["menu"].SyncActive) ) {
window.parent.frames["menu"].SyncActive("' . $browse_url . '");
}
}
';
}
$ret .= '</script>' . "\n";
if ( EDITING_MODE != EDITING_MODE_BROWSE ) {
// add form, so admin scripts could work
$ret .= '<form id="kernel_form" name="kernel_form" enctype="multipart/form-data" method="post" action="' . $browse_url . '">
<input type="hidden" name="MAX_FILE_SIZE" id="MAX_FILE_SIZE" value="' . MAX_UPLOAD_SIZE . '" />
<input type="hidden" name="sid" id="sid" value="' . $this->Application->GetSID() . '" />
</form>';
}
return $ret;
}
/**
* Prints "Edit Page" button on cms page
*
* @param Array $params
* @return string
*/
function EditPage($params)
{
if ( $this->Application->GetVar('preview') ) {
// prevents draft preview function to replace last template in session and break page/content block editing process
$this->Application->SetVar('skip_last_template', 1);
}
if (!EDITING_MODE) {
return '';
}
$display_mode = array_key_exists('mode', $params) ? $params['mode'] : false;
unset($params['mode']);
$edit_code = '';
$page =& $this->_getPage($params);
if (!$page->isLoaded() || (($display_mode != 'end') && (EDITING_MODE == EDITING_MODE_BROWSE))) {
// when "EditingScripts" tag is not used, make sure, that scripts are also included
return $this->EditingScripts($params);
}
// show "EditPage" button only for pages, that exists in structure
if ($display_mode != 'end') {
$edit_btn = $edit_url = '';
if ( EDITING_MODE == EDITING_MODE_CONTENT ) {
$item_prefix = isset($params['item_prefix']) ? $params['item_prefix'] : '';
unset($params['item_prefix']);
if ( $item_prefix ) {
$params['button_class'] = 'cms-section-properties-btn';
$edit_btn = $this->Application->ProcessParsedTag($item_prefix, 'AdminEditButton', $params) . "\n";
}
else {
$edit_btn = $this->AdminEditButton($params) . "\n"; // "st" object must be loaded before this
}
}
elseif ( EDITING_MODE == EDITING_MODE_DESIGN ) {
$url_params = Array(
'pass' => 'm,theme,theme-file',
'm_opener' => 'd',
'theme_id' => $this->Application->GetVar('m_theme'),
'theme_mode' => 't',
'theme_event' => 'OnEdit',
'theme-file_id' => $this->_getThemeFileId(),
'front' => 1,
'__URLENCODE__' => 1,
'__NO_REWRITE__'=> 1,
'index_file' => 'index.php',
);
$edit_url = $this->Application->HREF('themes/file_edit', ADMIN_DIRECTORY, $url_params);
$button1_icon = $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/save_button.gif';
$button1_title = $this->Application->Phrase('la_btn_SaveChanges', false, true);
$button1_code = '<button style="background-image: url(' . $button1_icon . '); onclick="aTemplateManager.saveLayout(); return false;" class="cms-btn-new cms-save-layout-btn">' . $button1_title . '</button>';
$button2_icon = $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/cancel_button.gif';
$button2_title = $this->Application->Phrase('la_btn_Cancel', false, true);
$button2_code = '<button style="background-image: url(' . $button2_icon . '); onclick="aTemplateManager.cancelLayout(); return false;" class="cms-btn-new cms-cancel-layout-btn">' . $button2_title . '</button>';
$button3_icon = $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/section_properties.png';
$button3_title = $this->Application->Phrase('la_btn_SectionTemplate', false, true);
$button3_code = '<button style="background-image: url(' . $button3_icon . ');' . ($display_mode === false ? ' margin: 0px;' : '') . '" onclick="$form_name=\'kf_'.$page->GetID().'\'; std_edit_item(\'theme\', \'themes/file_edit\');" class="cms-btn-new cms-section-properties-btn">' . $button3_title . '</button>';
$edit_btn .= '<div class="cms-layout-btn-container"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . '>' . $button1_code . $button2_code . '</div>' . $button3_code . "\n";
}
if ( $display_mode == 'start' ) {
// button with border around the page
if ( EDITING_MODE == EDITING_MODE_CONTENT ) {
$tabs = "\n" . str_repeat("\t", 9);
$base_url = $this->Application->BaseURL();
$toolbar_hidden = $this->Application->GetVar('toolbar_hidden');
$edit_code .= '
<div>
<div id="cms-editing-notice">
<div class="top">
<a href="#" id="cms-close-editing-notice"></a>
<span prev_editors=""></span>
</div>
<div class="bottom"></div>
</div>
<div id="cms-revision-dropdown">
<div class="top"></div>
<div class="bottom"></div>
</div>
</div>';
if ( $this->Application->ConfigValue('EnablePageContentRevisionControl') ) {
$edit_code .= '<div id="cms-revision-toolbar-layer"' . ($toolbar_hidden ? ' style="top: -56px;"' : '') . '>
<div id="cms-revision-toolbar">
<script type="text/javascript">
var a_toolbar = new ToolBar(undefined, undefined, "' . $base_url . '#MODULE#/admin_templates/img/");
' . $this->toolbarButton('select', 'la_ToolTip_Save', $tabs) . $this->toolbarButton('delete', 'la_ToolTip_Discard', $tabs) . $tabs . 'a_toolbar.AddButton( new ToolBarSeparator("sep1") );';
if ( $this->Application->CheckAdminPermission('CATEGORY.REVISION.MODERATE', 0) ) {
$edit_code .= $this->toolbarButton('approve', 'la_ToolTip_Publish', $tabs) . $this->toolbarButton('decline', 'la_ToolTip_Decline', $tabs) . $tabs . 'a_toolbar.AddButton( new ToolBarSeparator("sep2") );';
}
$edit_code .= $this->toolbarButton('preview', 'la_ToolTip_Preview', $tabs);
if ( $this->Application->CheckAdminPermission('CATEGORY.REVISION.HISTORY.VIEW', 0) ) {
$edit_code .= $this->toolbarButton('history', 'la_ToolTip_History', $tabs);
}
$edit_code .= $tabs . 'a_toolbar.Render();' . "\n";
$revision = $this->Application->recallObject('page-revision.current');
/* @var $revision kDBItem */
- if ( !$revision->GetDBField('IsDraft') ) {
- $edit_code .= $tabs . 'a_toolbar.DisableButton("select");' . $tabs . 'a_toolbar.DisableButton("delete");' . $tabs . 'a_toolbar.DisableButton("preview");';
- }
-
- if ( $revision->GetDBField('Status') == STATUS_ACTIVE || $revision->GetDBField('IsDraft') ) {
- $edit_code .= $tabs . 'a_toolbar.DisableButton("approve");';
- }
+ $page_helper = $this->Application->recallObject('PageHelper');
+ /* @var $page_helper PageHelper */
- if ( $revision->GetDBField('Status') == STATUS_DISABLED || $revision->GetDBField('IsLive') || $revision->GetDBField('IsDraft') ) {
- $edit_code .= $tabs . 'a_toolbar.DisableButton("decline");';
+ foreach ( $page_helper->getToolbarButtonsState($revision) as $toolbar_button => $is_enabled ) {
+ $edit_code .= $tabs . 'a_toolbar.SetEnabled("' . $toolbar_button . '", ' . json_encode($is_enabled) . ');';
}
$publishing_tools = $this->Application->Phrase('la_btn_PublishingTools', false, true);
$edit_code .= substr($tabs, 0, -1) . '</script>
<div id="cms-current-revision-info">
<span class="revision-title"></span>
<div class="draft-saved"></div>
</div>
<a href="#" id="cms-close-toolbar"></a>
<div class="cms-clear"></div>
</div>
<a href="#" id="cms-toggle-revision-toolbar"' . ($toolbar_hidden ? '' : ' class="opened"') . '><span>' . $publishing_tools . '</span></a>
</div>' . "\n";
}
}
$edit_code .= '<div class="cms-section-properties-btn-container">' . $edit_btn . '<div class="cms-btn-content">';
}
else {
// button without border around the page
$edit_code .= $edit_btn;
}
}
if ($display_mode == 'end') {
// draw border around the page
$edit_code .= '</div></div>';
}
if ($display_mode != 'end') {
if ( EDITING_MODE == EDITING_MODE_CONTENT ) {
$url_params = Array(
'pass' => 'm',
'm_opener' => 'd',
'm_cat_id' => $page->GetID(),
'__URLENCODE__' => 1,
'__NO_REWRITE__'=> 1,
'front' => 1,
'index_file' => 'index.php',
);
$revision = $this->Application->GetVar('revision');
if ( $revision ) {
$url_params['revision'] = $revision;
}
$page_admin_url = $this->Application->HREF('', ADMIN_DIRECTORY, $url_params);
$edit_code .= '<form method="POST" style="display: inline; margin: 0px" name="kf_revisions_'.$page->GetID().'" id="kf_revisions_'.$page->GetID().'" action="' . $page_admin_url . '">
<input type="hidden" name="revision" value="' . $this->Application->GetVar('revision', 0) . '"/>
</form>';
}
if ( $edit_url ) {
$edit_code .= '<form method="POST" style="display: inline; margin: 0px" name="kf_' . $page->GetID() . '" id="kf_' . $page->GetID() . '" action="' . $edit_url . '"></form>';
}
// when "EditingScripts" tag is not used, make sure, that scripts are also included
$edit_code .= $this->EditingScripts($params);
}
return $edit_code;
}
function toolbarButton($name, $title, $tabs)
{
- $phrase = $this->Application->Phrase($title, false, true);
+ $action = 'function() { aTemplateManager.revisionToolbarClick("' . $name . '"); }';
+ $phrase = kUtil::escape($this->Application->Phrase($title, false, true), kUtil::ESCAPE_HTML . '+' . kUtil::ESCAPE_JS);
- return $tabs . 'a_toolbar.AddButton( new ToolBarButton("' . $name . '", "' . kUtil::escape($phrase, kUtil::ESCAPE_HTML . '+' . kUtil::ESCAPE_JS) . '") );';
+ return $tabs . 'a_toolbar.AddButton(new ToolBarButton("' . $name . '", "' . $phrase . '", ' . $action . '));';
}
function _getThemeFileId()
{
$template = $this->Application->GetVar('t');
if (!$this->Application->TemplatesCache->TemplateExists($template) && !$this->Application->isAdmin) {
$cms_handler = $this->Application->recallObject($this->Prefix . '_EventHandler');
/* @var $cms_handler CategoriesEventHandler */
$template = ltrim($cms_handler->GetDesignTemplate(), '/');
}
$file_path = dirname($template) == '.' ? '' : '/' . dirname($template);
$file_name = basename($template);
$sql = 'SELECT FileId
FROM ' . TABLE_PREFIX . 'ThemeFiles
WHERE (ThemeId = ' . (int)$this->Application->GetVar('m_theme') . ') AND (FilePath = ' . $this->Conn->qstr($file_path) . ') AND (FileName = ' . $this->Conn->qstr($file_name . '.tpl') . ')';
return $this->Conn->GetOne($sql);
}
/**
* Creates a button for editing item in Admin Console
*
* @param Array $params
* @return string
* @access protected
*/
protected function AdminEditButton($params)
{
if ( EDITING_MODE != EDITING_MODE_CONTENT ) {
return '';
}
$object = $this->getObject($params);
/* @var $object kDBItem */
$params['item_prefix'] = 'c';
if ( $this->Prefix == 'st' ) {
$params['button_icon'] = 'section_properties.png';
$params['button_class'] = 'cms-section-properties-btn';
$params['button_title'] = 'la_btn_SectionProperties';
}
return parent::AdminEditButton($params);
}
/**
* Builds site menu
*
* @param Array $params
* @return string
*/
function CachedMenu($params)
{
$menu_helper = $this->Application->recallObject('MenuHelper');
/* @var $menu_helper MenuHelper */
return $menu_helper->menuTag($this->getPrefixSpecial(), $params);
}
/**
* Trick to allow some kind of output formatting when using CachedMenu tag
*
* @param Array $params
* @return bool
*/
function SplitColumn($params)
{
return $this->Application->GetVar($params['i']) > ceil($params['total'] / $params['columns']);
}
/**
* Returns direct children count of given category
*
* @param Array $params
* @return int
*/
function HasSubCats($params)
{
$sql = 'SELECT COUNT(*)
FROM ' . TABLE_PREFIX . 'Categories
WHERE ParentId = ' . $params['cat_id'];
return $this->Conn->GetOne($sql);
}
/**
* Prints sub-pages of given/current page.
*
* @param Array $params
* @return string
* @todo This could be reached by using "parent_cat_id" parameter. Only difference here is new block parameter "path". Need to rewrite.
*/
function PrintSubPages($params)
{
$list = $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List', $params);
/* @var $list kDBList */
$category_id = array_key_exists('category_id', $params) ? $params['category_id'] : $this->Application->GetVar('m_cat_id');
$list->addFilter('current_pages', TABLE_PREFIX . 'CategoryItems.CategoryId = ' . $category_id);
$list->Query();
$list->GoFirst();
$o = '';
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
while (!$list->EOL()) {
$block_params['path'] = $list->GetDBField('Path');
$o .= $this->Application->ParseBlock($block_params);
$list->GoNext();
}
return $o;
}
/**
* Builds link for browsing current page on Front-End
*
* @param Array $params
* @return string
*/
function PageBrowseLink($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$themes_helper = $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$site_config_helper = $this->Application->recallObject('SiteConfigHelper');
/* @var $site_config_helper SiteConfigHelper */
$settings = $site_config_helper->getSettings();
$url_params = Array (
'm_cat_id' => $object->GetID(),
'm_theme' => $themes_helper->getCurrentThemeId(),
'editing_mode' => $settings['default_editing_mode'],
'pass' => 'm',
'admin' => 1,
);
if ($this->Application->ConfigValue('UseModRewrite')) {
$url_params['__MOD_REWRITE__'] = 1;
}
else {
$url_params['index_file'] = 'index.php';
}
return $this->Application->HREF($object->GetDBField('NamedParentPath'), '_FRONT_END_', $url_params);
}
/**
* Builds a link for securely accessing a page later (even if it will not be publicly accessible)
*
* @param Array $params
* @return string
* @access protected
*/
protected function DirectLink($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$themes_helper = $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$url_params = Array (
'm_cat_id' => $object->GetID(),
'm_theme' => $themes_helper->getCurrentThemeId(),
'pass' => 'm',
'authkey' => $object->GetDBField('DirectLinkAuthKey'),
'__SSL__' => 0,
'__NO_SID__' => 0,
);
if ($this->Application->ConfigValue('UseModRewrite')) {
$url_params['__MOD_REWRITE__'] = 1;
}
else {
$url_params['index_file'] = 'index.php';
}
return $this->Application->HREF($object->GetDBField('NamedParentPath'), '_FRONT_END_', $url_params);
}
/**
* Builds link to category as a cms page
*
* @param Array $params
* @return string
*/
function ContentPageLink($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$params['t'] = mb_strtolower($object->GetDBField('NamedParentPath'));
$params['m_cat_id'] = 0;
return $this->Application->ProcessParsedTag('m', 'Link', $params);
}
/**
* Prepares cms page description for search result page
*
* @param Array $params
* @return string
*/
function SearchDescription($params)
{
$object = $this->getObject($params);
$desc = $object->GetField('MetaDescription');
if (!$desc) {
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'PageContent
WHERE PageId = ' . $object->GetID() . ' AND ContentNum = 1';
$content = $this->Conn->GetRow($sql);
if ($content['l'.$this->Application->GetVar('m_lang').'_Content']) {
$desc = $content['l'.$this->Application->GetVar('m_lang').'_Content'];
}
else {
$desc = $content['l'.$this->Application->GetDefaultLanguageId().'_Content'];
}
}
return mb_substr($desc, 0, 300).(mb_strlen($desc) > 300 ? '...' : '');
}
/**
* Simplified version of "c:CategoryLink" for "c:PrintList"
*
* @param Array $params
* @return string
* @todo Used? Needs refactoring.
*/
function EnterCatLink($params)
{
$object = $this->getObject($params);
$url_params = Array ('pass' => 'm', 'm_cat_id' => $object->GetID());
return $this->Application->HREF($params['template'], '', $url_params);
}
/**
* Simplified version of "c:CategoryPath", that do not use blocks for rendering
*
* @param Array $params
* @return string
* @todo Used? Maybe needs to be removed.
*/
function PagePath($params)
{
$object = $this->getObject($params);
$path = $object->GetField('CachedNavbar');
if ($path) {
$items = explode('&|&', $path);
array_shift($items);
return implode(' -&gt; ', $items);
}
return '';
}
/**
* Returns configuration variable value
*
* @param Array $params
* @return string
* @todo Needs to be replaced with "m:GetConfig" tag; Not used now (were used on structure_edit.tpl).
*/
function AllowManualFilenames($params)
{
return $this->Application->ConfigValue('ProjCMSAllowManualFilenames');
}
/**
* Draws path to current page (each page can be link to it)
*
* @param Array $params
* @return string
*/
function CurrentPath($params)
{
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $block_params['render_as'];
$object = $this->Application->recallObject($this->Prefix);
/* @var $object kDBItem */
$category_ids = explode('|', substr($object->GetDBField('ParentPath'), 1, -1));
$config = $this->getUnitConfig();
$language = (int)$this->Application->GetVar('m_lang');
if ( !$language ) {
$language = 1;
}
$sql = 'SELECT l' . $language . '_Name AS Name, NamedParentPath
FROM ' . $config->getTableName() . '
WHERE ' . $config->getIDField() . ' IN (' . implode(',', $category_ids) . ')';
$categories_data = $this->Conn->Query($sql);
$ret = '';
foreach ($categories_data as $index => $category_data) {
if ( $category_data['Name'] == 'Content' ) {
continue;
}
$block_params['title'] = $category_data['Name'];
$block_params['template'] = preg_replace('/^Content\//i', '', $category_data['NamedParentPath']);
$block_params['is_first'] = $index == 1; // because Content is 1st element
$block_params['is_last'] = $index == count($categories_data) - 1;
$ret .= $this->Application->ParseBlock($block_params);
}
return $ret;
}
/**
* Synonim to PrintList2 for "onlinestore" theme
*
* @param Array $params
* @return string
*/
function ListPages($params)
{
return $this->PrintList2($params);
}
/**
* Returns information about parser element locations in template
*
* @param Array $params
* @return mixed
*/
function BlockInfo($params)
{
if (!EDITING_MODE) {
return '';
}
$template_helper = $this->Application->recallObject('TemplateHelper');
/* @var $template_helper TemplateHelper */
return $template_helper->blockInfo( $params['name'] );
}
/**
* Hide all editing tabs except permission tab, when editing "Home" (ID = 0) category
*
* @param Array $params
*/
function ModifyUnitConfig($params)
{
$root_category = $this->Application->RecallVar('IsRootCategory_' . $this->Application->GetVar('m_wid'));
if ( !$root_category ) {
return;
}
$config = $this->getUnitConfig();
$edit_tab_preset = $config->getEditTabPresetByName('Default');
$config->addEditTabPresets(Array (
'Default' => Array ('permissions' => $edit_tab_preset['permissions'])
));
}
/**
* Prints catalog export templates
*
* @param Array $params
* @return string
*/
function PrintCatalogExportTemplates($params)
{
$ret = Array ();
$prefixes = explode(',', $params['prefixes']);
foreach ($prefixes as $prefix) {
if ( $this->Application->prefixRegistred($prefix) ) {
$module_path = $this->Application->getUnitConfig($prefix)->getModuleFolder() . '/';
$module_name = $this->Application->findModule('Path', $module_path, 'Name');
$ret[$prefix] = mb_strtolower($module_name) . '/export';
}
}
return json_encode($ret);
}
/**
* Checks, that "view in browse mode" functionality available
*
* @param Array $params
* @return bool
*/
function BrowseModeAvailable($params)
{
$valid_special = $params['Special'] != 'user';
$not_selector = $this->Application->GetVar('type') != 'item_selector';
return $valid_special && $not_selector;
}
/**
* Returns a link for editing product
*
* @param Array $params
* @return string
*/
function ItemEditLink($params)
{
$object = $this->getObject($params);
/* @var $object kDBList */
$config = $this->getUnitConfig();
$edit_template = $config->getAdminTemplatePath() . '/' . $config->getAdminTemplatePrefix() . 'edit';
$url_params = Array (
'm_opener' => 'd',
$this->Prefix.'_mode' => 't',
$this->Prefix.'_event' => 'OnEdit',
$this->Prefix.'_id' => $object->GetID(),
'm_cat_id' => $object->GetDBField('ParentId'),
'pass' => 'all,'.$this->Prefix,
'no_pass_through' => 1,
);
return $this->Application->HREF($edit_template,'', $url_params);
}
function RelevanceIndicator($params)
{
$object = $this->getObject($params);
/* @var $object kDBItem */
$search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
$sql = 'SELECT Relevance
FROM '.$search_results_table.'
WHERE ResourceId = '.$object->GetDBField('ResourceId');
$percents_off = (int)(100 - (100 * $this->Conn->GetOne($sql)));
$percents_off = ($percents_off < 0) ? 0 : $percents_off;
if ($percents_off) {
$params['percent_off'] = $percents_off;
$params['percent_on'] = 100 - $percents_off;
$params['name'] = $this->SelectParam($params, 'relevance_normal_render_as,block_relevance_normal');
}
else {
$params['name'] = $this->SelectParam($params, 'relevance_full_render_as,block_relevance_full');
}
return $this->Application->ParseBlock($params);
}
/**
* Returns list of categories, that have category add/edit permission
*
* @param Array $params
* @return string
*/
function AllowedCategoriesJSON($params)
{
if ($this->Application->RecallVar('user_id') == USER_ROOT) {
$categories = true;
}
else {
$object = $this->getObject($params);
/* @var $object kDBItem */
$perm_helper = $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$perm_prefix = $this->getUnitConfig()->getPermItemPrefix();
$categories = $perm_helper->getPermissionCategories($perm_prefix . '.' . ($object->IsNewItem() ? 'ADD' : 'MODIFY'));
}
$json_helper = $this->Application->recallObject('JSONHelper');
/* @var $json_helper JSONHelper */
return $json_helper->encode($categories);
}
function PageEditable($params)
{
if ($this->Application->isDebugMode()) {
return true;
}
$object = $this->getObject($params);
/* @var $object kDBItem */
return !$object->GetDBField('Protected');
}
/**
* Returns element for "__item__" navigation bar part
*
* @param Array $params
* @return string
* @access protected
*/
protected function CategoryItemElement($params)
{
$category_helper = $this->Application->recallObject('CategoryHelper');
/* @var $category_helper CategoryHelper */
$navigation_bar = $this->Application->recallObject('kNavigationBar');
/* @var $navigation_bar kNavigationBar */
$category_id = isset($params['cat_id']) ? $params['cat_id'] : $this->Application->GetVar('m_cat_id');
$parent_path = explode('|', substr($navigation_bar->getParentPath($category_id), 1, -1));
array_shift($parent_path); // remove "Content" category
$module_info = $category_helper->getCategoryModule($params, $parent_path);
if ( !$module_info ) {
return '';
}
$module_prefix = $module_info['Var'];
$object = $this->Application->recallObject($module_prefix);
/* @var $object kCatDBItem */
$title_field = $this->Application->getUnitConfig($module_prefix)->getTitleField();
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
$block_params['title'] = $object->GetField($title_field);
$block_params['prefix'] = $module_prefix;
return $this->Application->ParseBlock($block_params);
}
}
\ No newline at end of file
Index: branches/5.3.x/core/units/helpers/fck_helper.php
===================================================================
--- branches/5.3.x/core/units/helpers/fck_helper.php (revision 15945)
+++ branches/5.3.x/core/units/helpers/fck_helper.php (revision 15946)
@@ -1,411 +1,625 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class fckFCKHelper extends kHelper {
var $Config = Array();
/**
* Currently selected folder
*
* @var string
* @access protected
*/
protected $folder = '';
/**
* Current sorting field
*
* @var string
* @access protected
*/
protected $sortField = '';
/**
* Current sorting direction
*
* @var string
* @access protected
*/
protected $sortDirection = '';
public function __construct()
{
parent::__construct();
$this->folder = $this->Application->GetVar('folder');
$this->sortField = $this->Application->GetVar('sort_by');
$this->sortDirection = $this->Application->GetVar('order_by');
$this->Config['AllowedExtensions']['Files'] = Array('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');
$this->Config['ExtensionIcons'] = 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');
}
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);*/
return mkdir($folderPath);
}
function IsAllowedExtension($folder, $file_name)
{
$ext = strtolower( pathinfo($file_name, PATHINFO_EXTENSION) );
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;
}
/**
* Returns list of sub-folders from given folder (automatically excludes system folders)
*
* @param string $files_dir
* @return Array
* @access public
*/
public function ReadFolders($files_dir)
{
$ret = Array ();
$system_folders = defined('KERNEL_SYSTEM_FOLDERS') ? KERNEL_SYSTEM_FOLDERS : Array ('icons', 'CVS', '.svn');
try {
$iterator = new DirectoryIterator($files_dir);
/* @var $file_info DirectoryIterator */
}
catch (UnexpectedValueException $e) {
return $ret;
}
foreach ($iterator as $file_info) {
$filename = $file_info->getFilename();
if ( $file_info->isDir() && !$file_info->isDot() ) {
$ret[] = $filename;
}
}
return array_diff($ret, $system_folders);
}
/**
* Returns list of files in given folder
*
* @param string $files_dir
* @return Array
* @access public
*/
public function ReadFiles($files_dir)
{
$ret = Array ();
try {
$iterator = new DirectoryIterator($files_dir);
/* @var $file_info DirectoryIterator */
}
catch (UnexpectedValueException $e) {
return $ret;
}
foreach ($iterator as $file_info) {
if ( !$file_info->isDir() ) {
$ret[] = $file_info->getFilename();
}
}
return $ret;
}
/**
* Returns xml containing list of folders in current folder
*
* @return string
* @access public
*/
public function PrintFolders()
{
$files_dir = WRITEABLE . '/user_files/' . $this->folder . '/';
$sub_folders = $this->ReadFolders($files_dir);
natcasesort($sub_folders);
$ret = $this->_buildFoldersXML($sub_folders, 'folder2');
if ( $this->sortField == 'name' && $this->sortDirection == '_desc' ) {
$sub_folders = array_reverse($sub_folders);
}
$ret .= $this->_buildFoldersXML($sub_folders, 'folder');
return $ret;
}
/**
* Build XML, that will output folders for FCKEditor
*
* @param Array $sub_folders
* @param string $xml_node
* @return string
*/
protected function _buildFoldersXML($sub_folders, $xml_node)
{
$ret = '';
foreach ($sub_folders as $sub_folder) {
$ret .= '<' . $xml_node . ' path="' . $this->folder . "/" . $sub_folder . '">' . $sub_folder . '</' . $xml_node . '>' . "\n";
}
return $ret;
}
/**
* Transforms filesize in bytes into kilobytes
*
* @param int $size
* @return int
* @access protected
*/
protected function CalculateFileSize($size)
{
if ( $size > 0 ) {
$size = round($size / 1024);
$size = ($size < 1) ? 1 : $size;
}
return $size;
}
/**
* Detects icon for given file extension
*
* @param string $file
* @return string
* @access protected
*/
protected function CheckIconType($file)
{
$ext = strtolower( pathinfo($file, PATHINFO_EXTENSION) );
return $ext && in_array($ext, $this->Config['ExtensionIcons']) ? $ext : 'default.icon';
}
/**
* Build one file xml node
*
* @param int $size
* @param string $url
* @param string $icon
* @param string $date
* @param string $file_name
* @return string
*/
protected function _buildFileXml($size,$url,$icon,$date,$file_name)
{
return '<file size="' . $size . '" url="' . $url . '" icon="' . $icon . '" date="' . $date . '">' . $file_name . '</file>' . "\n";
}
/**
* Returns xml containing list of files in current folder
*
* @return string
* @access public
*/
public function PrintFiles()
{
$files_dir = WRITEABLE . '/user_files/' . $this->folder . '/';
$files_url = BASE_PATH . str_replace(DIRECTORY_SEPARATOR, '/', WRITEBALE_BASE) . '/user_files/' . $this->folder . '/';
$aFiles = $this->ReadFiles($files_dir);
$ret = '';
$date_format = "m/d/Y h:i A";
natcasesort($aFiles);
if ( $this->sortField == 'name' && $this->sortDirection == '_desc' ) {
$aFiles = array_reverse($aFiles, TRUE);
}
$aFilesSize = $aFilesDate = Array ();
foreach ($aFiles as $k => $v) {
$aFilesSize[$k] = filesize($files_dir . $v);
$aFilesDate[$k] = filectime($files_dir . $v);
}
if ( $this->sortField == 'name' ) {
foreach ($aFiles as $k => $file) {
$size = $this->CalculateFileSize($aFilesSize[$k]);
$date = date($date_format, $aFilesDate[$k]);
$icon = $this->CheckIconType($file);
$ret .= $this->_buildFileXml($size, $files_url . $file, $icon, $date, $file);
}
}
if ( $this->sortField == 'date' ) {
asort($aFilesDate);
if ( $this->sortDirection == '_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->_buildFileXml($size, $files_url . $file, $icon, $date, $file);
}
}
if ( $this->sortField == 'size' ) {
asort($aFilesSize);
if ( $this->sortDirection == '_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->_buildFileXml($size, $files_url . $file, $icon, $date, $file);
}
}
return $ret;
}
function UploadFile()
{
$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, $this->Config['AllowedExtensions'][$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, '.' ) ) ;
}
+ public function CKEditorTag($editor_name, $editor_value, $params)
+ {
+ $editor = $this->prepareConfig($this->getEditor(), $params);
+
+ $width = $this->normalizeDimension($params['width']);
+ $height = $this->normalizeDimension($params['height']);
+
+ $editor->textareaAttributes = Array (
+ 'style' => 'width: ' . $width . '; height: ' . $height . ';'
+ );
+
+ $editor->config['height'] = $height; // editor area height
+
+ $events = Array (
+ 'configLoaded' => 'function(ev) { CKEDITOR.addCss(ev.editor.config.extraCss); }',
+ );
+
+ return $editor->editor($editor_name, $editor_value, Array (), $events);
+ }
+
+ public function CKEditorInlineTag($editor_name, $params)
+ {
+ $editor = $this->prepareConfig($this->getEditor(), $params);
+
+ $events = Array (
+ 'configLoaded' => 'function(ev) { CKEDITOR.addCss(ev.editor.config.extraCss); }',
+ 'focus' => 'function(ev) { $("body").trigger("InlineEditor.Focus", [ev]); }',
+ 'blur' => 'function(ev) { $("body").trigger("InlineEditor.Blur", [ev]); }',
+ );
+
+ return $editor->inline($editor_name, Array (), $events);
+ }
+
+ /**
+ * Adds measurement units to editor dimensions.
+ *
+ * @param string $dimension Dimension.
+ *
+ * @return string
+ */
+ protected function normalizeDimension($dimension)
+ {
+ if ( preg_match('/^[\d]+$/', $dimension) ) {
+ $dimension .= 'px';
+ }
+
+ return $dimension;
+ }
+
+ /**
+ * Returns editor instance.
+ *
+ * @return CKEditor
+ */
+ protected function getEditor()
+ {
+ include_once(FULL_PATH . EDITOR_PATH . 'ckeditor.php');
+ $editor = new CKeditor(BASE_PATH . EDITOR_PATH);
+ $editor->returnOutput = true;
+
+ return $editor;
+ }
+
+ /**
+ * Prepares editor config.
+ *
+ * @param CKEditor $editor Editor.
+ * @param array $tag_params Tag params.
+ *
+ * @return CKEditor
+ */
+ protected function prepareConfig(CKEditor $editor, array $tag_params)
+ {
+ $editor->lateLoad = array_key_exists('late_load', $tag_params) && $tag_params['late_load'];
+
+ list($styles_css, $styles_js) = $this->getStyles();
+
+ if ( isset($tag_params['toolbar']) ) {
+ $toolbar = $tag_params['toolbar'];
+ }
+ elseif ( isset($tag_params['mode']) && $tag_params['mode'] == 'inline' ) {
+ $toolbar = 'Inline';
+ }
+ else {
+ $toolbar = $this->Application->isDebugMode() ? 'DebugMode' : 'Default';
+ }
+
+ $editor->config = Array (
+ 'toolbar' => $toolbar,
+ 'baseHref' => $this->Application->BaseURL( rtrim(EDITOR_PATH, '/') ),
+ 'customConfig' => $this->getJavaScriptConfig(),
+ 'stylesSet' => 'portal:' . $styles_js,
+ 'contentsCss' => $styles_css,
+ 'Admin' => 1, // for custom file browser to work
+ 'K4' => 1, // for custom file browser to work
+ 'language' => $this->getLanguage(),
+ );
+
+ $this->injectTransitParams($editor, $this->getTransitParams($tag_params));
+
+ return $editor;
+ }
+
+ /**
+ * Transforms transit params into editor config.
+ *
+ * @param CKEditor $editor Editor.
+ * @param array $transit_params Transit params.
+ *
+ * @return void
+ */
+ protected function injectTransitParams(CKEditor $editor, array $transit_params)
+ {
+ if ( isset($transit_params['bgcolor']) && $transit_params['bgcolor'] ) {
+ $editor->config['extraCss'] = 'body { background-color: ' . $transit_params['bgcolor'] . '; }';
+ }
+
+ foreach ($transit_params as $param_name => $param_value) {
+ if ( !$param_value ) {
+ continue;
+ }
+
+ $param_key = str_replace(' ', '', ucwords(str_replace('_', ' ', $param_name)));
+ $param_key[0] = strtolower($param_key[0]);
+
+ $editor->config[$param_key] = $param_value;
+ }
+ }
+
+ /**
+ * Returns url to CSS and JS style configuration.
+ *
+ * @return array
+ */
+ protected function getStyles()
+ {
+ $theme_path = $this->Application->GetFrontThemePath() . '/inc';
+
+ if ( file_exists(FULL_PATH . $theme_path . '/style.css') ) {
+ $url_params = Array (
+ 'events[fck]' => 'OnGetsEditorStyles',
+ 'no_pass_through' => 1, 'pass' => 'm', 'no_amp' => 1
+ );
+
+ $styles_css = $this->Application->HREF('index', '_FRONT_END_', $url_params, 'index.php');
+ }
+ else {
+ $theme_path = rtrim(EDITOR_PATH, '/');
+ $styles_css = $this->Application->BaseURL($theme_path) . 'style.css';
+ }
+
+ $styles_js = $this->Application->BaseURL($theme_path) . 'styles.js';
+
+ return array($styles_css, $styles_js);
+ }
+
+ /**
+ * Returns url to JavaScript configuration file.
+ *
+ * @return string
+ */
+ protected function getJavaScriptConfig()
+ {
+ if ( file_exists(SYSTEM_PRESET_PATH . DIRECTORY_SEPARATOR . 'inp_ckconfig.js') ) {
+ $file_helper = $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ return $file_helper->pathToUrl(SYSTEM_PRESET_PATH . DIRECTORY_SEPARATOR . 'inp_ckconfig.js');
+ }
+
+ return $this->Application->BaseURL() . 'core/admin_templates/js/inp_ckconfig.js';
+ }
+
+ /**
+ * Returns CKEditor locale, that matches default site language.
+ *
+ * @return string
+ */
+ protected function getLanguage()
+ {
+ static $language_code = null;
+
+ if ( !isset($language_code) ) {
+ $language_code = 'en'; // default value
+
+ if ( $this->Application->isAdmin ) {
+ $language_id = $this->Application->Phrases->LanguageId;
+ }
+ else {
+ $language_id = $this->Application->GetDefaultLanguageId(); // $this->Application->GetVar('m_lang');
+ }
+
+ $sql = 'SELECT Locale
+ FROM ' . $this->Application->getUnitConfig('lang')->getTableName() . '
+ WHERE LanguageId = ' . $language_id;
+ $locale = strtolower($this->Conn->GetOne($sql));
+
+ if ( file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale . '.js') ) {
+ // found language file, that exactly matches locale name (e.g. "en")
+ $language_code = $locale;
+ }
+ else {
+ $locale = explode('-', $locale);
+
+ if ( file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale[0] . '.js') ) {
+ // language file matches first part of locale (e.g. "ru-RU")
+ $language_code = $locale[0];
+ }
+ }
+ }
+
+ return $language_code;
+ }
+
/**
* Returns transit parameters, that should be passed to every used CKEditor instance
*
* @param Array $tag_params
* @return Array
*/
public function getTransitParams($tag_params = Array ())
{
$ret = Array ();
$transit_params = Array ('bgcolor' => '', 'body_class' => '', 'body_id' => '');
foreach ($transit_params as $param_name => $default_value) {
$param_value = isset($tag_params[$param_name]) ? $tag_params[$param_name] : $this->Application->GetVar($param_name);
if ( $param_value || $default_value ) {
$ret[$param_name] = $param_value ? $param_value : $default_value;
}
}
return $ret;
}
}
\ No newline at end of file
Index: branches/5.3.x/core/units/helpers/page_helper.php
===================================================================
--- branches/5.3.x/core/units/helpers/page_helper.php (revision 15945)
+++ branches/5.3.x/core/units/helpers/page_helper.php (revision 15946)
@@ -1,275 +1,439 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class PageHelper extends kHelper {
/**
* Returns page info
*
* @param int $page_id
* @return Array
*/
function getPageInfo($page_id)
{
list ($user_id, $history_permission) = $this->getHistoryPermissionAndUser($page_id);
- $where_clause = Array (
+ $users = $this->getEditors($page_id, $user_id);
+
+ return array(
+ 'current_revision' => $this->getCurrentRevisionInfo(),
+ 'editors' => $users,
+ 'editors_warning' => $this->getEditorsWarning($users),
+ 'revisions' => $history_permission ? $this->getPageRevisions($page_id) : array(),
+ );
+ }
+
+ /**
+ * Returns current admin user id (even, when called from front-end) and it's revision history view permission
+ *
+ * @param int $page_id
+ * @return Array
+ */
+ protected function getHistoryPermissionAndUser($page_id)
+ {
+ $perm_helper = $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ $user_id = (int)$this->Application->RecallVar($this->Application->isAdmin ? 'user_id' : 'admin_user_id');
+ $history_permission = $perm_helper->CheckUserPermission($user_id, 'CATEGORY.REVISION.HISTORY.VIEW', 0, $page_id);
+
+ return Array ($user_id, $history_permission);
+ }
+
+ /**
+ * Returns information about given page editors.
+ *
+ * @param integer $page_id Page, that is being edited.
+ * @param integer $user_id User, who is editing a page.
+ *
+ * @return array
+ */
+ protected function getEditors($page_id, $user_id)
+ {
+ $where_clause = array(
'pr.PageId = ' . $page_id,
'pr.CreatedById <> ' . $user_id,
'pr.IsDraft = 1',
);
$sql = 'SELECT CASE pr.CreatedById WHEN ' . USER_ROOT . ' THEN "root" WHEN ' . USER_GUEST . ' THEN "Guest" ELSE IF(u.Username = "", u.Email, u.Username) END
FROM ' . $this->Application->getUnitConfig('page-revision')->getTableName() . ' pr
LEFT JOIN ' . TABLE_PREFIX . 'Users u ON u.PortalUserId = pr.CreatedById
WHERE (' . implode(') AND (', $where_clause) . ')';
- $users = $this->Conn->GetCol($sql);
- $page_revisions = Array ();
+ return $this->Conn->GetCol($sql);
+ }
+
+ /**
+ * Returns information about current revision.
+ *
+ * @return array
+ */
+ protected function getCurrentRevisionInfo()
+ {
+ $revision = $this->Application->recallObject('page-revision.current');
+ /* @var $revision kDBItem */
+
+ $status_label = $this->getRevisionStatusText($revision);
- if ( $history_permission ) {
- $tag_params = Array ('per_page' => -1, 'skip_parent_filter' => 1, 'requery' => 1, 'page_id' => $page_id);
+ $draft = $revision->GetDBField('IsDraft');
+ $title = $this->getAdminPhrase($draft ? 'la_title_EditingDraft' : 'la_title_ViewingRevision');
- $revisions = $this->Application->recallObject('page-revision.list', 'page-revision_List', $tag_params);
- /* @var $revisions kDBList */
-
- $revisions->Query();
- $revisions->GoFirst();
-
- $status_options = $revisions->GetFieldOptions('Status');
- $draft_label = $this->Application->Phrase('la_Draft', false, true);
- $title_label = $this->Application->Phrase('la_RevisionNumber', false, true);
- $by_label = $this->Application->Phrase('la_By', false, true);
-
- while ( !$revisions->EOL() ) {
- $status = $revisions->GetDBField('Status');
- $status_label = $this->Application->Phrase($status_options['options'][$status], false, true);
-
- $page_revisions[ 'r' . $revisions->GetDBField('RevisionNumber') ] = Array (
- 'title' => $revisions->GetDBField('IsDraft') ? $draft_label : sprintf($title_label, $revisions->GetDBField('RevisionNumber')),
- 'status' => $status,
- 'status_label' => mb_strtolower($status_label),
- 'datetime' => $revisions->GetField('CreatedOn'),
- 'author' => $by_label . ': ' . $revisions->GetField('CreatedById'),
- 'draft' => (int)$revisions->GetDBField('IsDraft'),
- );
+ $current_revision_info = array(
+ 'title' => sprintf($title, $revision->GetDBField('RevisionNumber'), $status_label),
+ 'status' => $revision->GetDBField('Status'),
+ 'saved' => '',
+ 'toolbar_state' => $this->getToolbarButtonsState($revision),
+ );
- $revisions->GoNext();
- }
+ $auto_save_time = $revision->GetDBField('AutoSavedOn');
+
+ if ( $auto_save_time ) {
+ $phrase = $this->getAdminPhrase($draft ? 'la_DraftSavedAt' : 'la_SavedAt');
+ $current_revision_info['saved'] = sprintf($phrase, $revision->GetField('AutoSavedOn_time') . ' (' . $this->getAgoTime($auto_save_time) . ')');
}
- $current_revision = $this->Application->recallObject('page-revision.current');
- /* @var $current_revision kDBItem */
+ return $current_revision_info;
+ }
- $revision_status = $current_revision->GetDBField('Status');
- $status_options = $current_revision->GetFieldOptions('Status');
- $status_label = $this->Application->Phrase($status_options['options'][$revision_status], false, true);
-
- $revision_phase = $current_revision->GetDBField('IsDraft') ? 'la_title_EditingDraft' : 'la_title_ViewingRevision';
- $revision_title = sprintf($this->Application->Phrase($revision_phase, false, true), $current_revision->GetDBField('RevisionNumber'), mb_strtolower($status_label));
- $current_revision_info = Array ('title' => $revision_title, 'status' => $revision_status, 'saved' => '');
-
- $autosave_time = $current_revision->GetDBField('AutoSavedOn');
-
- if ( $autosave_time ) {
- $phrase = $this->Application->Phrase($current_revision->GetDBField('IsDraft') ? 'la_DraftSavedAt' : 'la_SavedAt', false, true);
- $current_revision_info['saved'] = sprintf($phrase, $current_revision->GetField('AutoSavedOn_time') . ' (' . $this->getAgoTime($autosave_time) . ')');
+ /**
+ * Returns state of all CMS revision toolbar buttons.
+ *
+ * @param kDBItem $revision Page Revision.
+ *
+ * @return array
+ */
+ public function getToolbarButtonsState(kDBItem $revision)
+ {
+ $ret = array();
+
+ foreach ( $this->getToolbarButtons() as $toolbar_button ) {
+ $ret[$toolbar_button] = $this->isToolbarButtonEnabled($toolbar_button, $revision);
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Returns list of CMS revision toolbar buttons.
+ *
+ * @return array
+ */
+ protected function getToolbarButtons()
+ {
+ return array('select', 'delete', 'approve', 'decline', 'preview', 'history');
+ }
+
+ /**
+ * Checks if given CMS revision toolbar button is enabled for given revision.
+ *
+ * @param string $button_name Toolbar button name.
+ * @param kDBItem $revision Revision to check against.
+ *
+ * @return boolean
+ */
+ protected function isToolbarButtonEnabled($button_name, kDBItem $revision)
+ {
+ $is_draft = $revision->GetDBField('IsDraft');
+
+ if ( $button_name == 'select' || $button_name == 'delete' || $button_name == 'preview' ) {
+ return (bool)$is_draft;
+ }
+
+ if ( $button_name == 'approve' ) {
+ return $revision->GetDBField('Status') != STATUS_ACTIVE && !$is_draft;
}
+ if ( $button_name == 'decline' ) {
+ return $revision->GetDBField('Status') != STATUS_DISABLED && !$revision->GetDBField('IsLive') && !$is_draft;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns warning to be shown in case of parallel editing attempts.
+ *
+ * @param array $users Users, that are editing a page.
+ *
+ * @return string
+ */
+ protected function getEditorsWarning(array $users)
+ {
$ml_helper = $this->Application->recallObject('kMultiLanguageHelper');
/* @var $ml_helper kMultiLanguageHelper */
- $currently_editing = $ml_helper->getPluralPhrase(
+ $ret = $ml_helper->getPluralPhrase(
count($users),
- Array (
+ array(
'phrase1' => 'la_PageCurrentlyEditing1',
'phrase2' => 'la_PageCurrentlyEditing2',
'phrase5' => 'la_PageCurrentlyEditing5',
),
false, true
);
- $currently_editing = sprintf($currently_editing, implode(', ', $users));
+ return sprintf($ret, implode(', ', $users));
+ }
+
+ /**
+ * Returns information about given page revisions.
+ *
+ * @param integer $page_id Page, that is being edited.
+ *
+ * @return array
+ */
+ protected function getPageRevisions($page_id)
+ {
+ $ret = Array ();
- return Array ('current_revision' => $current_revision_info, 'editors' => $users, 'editors_warning' => $currently_editing, 'revisions' => $page_revisions);
+ $tag_params = Array ('per_page' => -1, 'skip_parent_filter' => 1, 'requery' => 1, 'page_id' => $page_id);
+
+ $revisions = $this->Application->recallObject('page-revision.list', 'page-revision_List', $tag_params);
+ /* @var $revisions kDBList */
+
+ $revisions->Query();
+ $revisions->GoFirst();
+
+ while ( !$revisions->EOL() ) {
+ $ret[ 'r' . $revisions->GetDBField('RevisionNumber') ] = array(
+ 'title' => $this->getRevisionTitle($revisions),
+ 'status' => $revisions->GetDBField('Status'),
+ 'status_label' => $this->getRevisionStatusText($revisions),
+ 'datetime' => $revisions->GetField('CreatedOn'),
+ 'author' => $this->getRevisionAuthor($revisions),
+ 'draft' => (int)$revisions->GetDBField('IsDraft'),
+ );
+
+ $revisions->GoNext();
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Returns title for given revision.
+ *
+ * @param kDBBase $revision Page Revision.
+ *
+ * @return string
+ */
+ protected function getRevisionTitle(kDBBase $revision)
+ {
+ if ( $revision->GetDBField('IsDraft') ) {
+ return $this->getAdminPhrase('la_Draft');
+ }
+
+ $title = $this->getAdminPhrase('la_RevisionNumber');
+
+ return sprintf($title, $revision->GetDBField('RevisionNumber'));
+ }
+
+ /**
+ * Returns status text for given revision.
+ *
+ * @param kDBBase $revision Page Revision.
+ *
+ * @return string
+ */
+ protected function getRevisionStatusText(kDBBase $revision)
+ {
+ $status = $revision->GetDBField('Status');
+ $options = $revision->GetFieldOptions('Status');
+
+ return mb_strtolower($this->getAdminPhrase($options['options'][$status]));
+ }
+
+ /**
+ * Returns author of given revision.
+ *
+ * @param kDBBase $revision Page Revision.
+ *
+ * @return string
+ */
+ protected function getRevisionAuthor(kDBBase $revision)
+ {
+ $by_label = $this->getAdminPhrase('la_By');
+
+ return $by_label . ': ' . $revision->GetField('CreatedById');
+ }
+
+ /**
+ * Returns Admin's non-editable translation of given phrase.
+ *
+ * @param string $label Phrase label.
+ *
+ * @return string
+ */
+ protected function getAdminPhrase($label)
+ {
+ return $this->Application->Phrase($label, false, true);
}
/**
* Returns time passed between 2 given dates in "X minutes Y seconds ago" format
*
* @param int $from_date
* @param int $to_date
+ * @param integer $max_levels
+ *
* @return string
*/
- function getAgoTime($from_date, $to_date = null, $max_levels = 1)
+ public function getAgoTime($from_date, $to_date = null, $max_levels = 1)
{
$blocks = Array (
Array ('name' => 'year', 'amount' => 60*60*24*365),
Array ('name' => 'month' ,'amount' => 60*60*24*31),
Array ('name' => 'week', 'amount' => 60*60*24*7),
Array ('name' => 'day', 'amount' => 60*60*24),
Array ('name' => 'hour', 'amount' => 60*60),
Array ('name' => 'minute', 'amount' => 60),
Array ('name' => 'second', 'amount' => 1),
);
if ( !isset($to_date) ) {
$to_date = time();
}
$diff = abs($to_date - $from_date);
if ( $diff == 0 ) {
return 'now';
}
$current_level = 1;
$result = Array ();
foreach ($blocks as $block) {
if ($current_level > $max_levels) {
break;
}
if ( $diff / $block['amount'] >= 1 ) {
$amount = floor($diff / $block['amount']);
$plural = $amount > 1 ? 's' : '';
$result[] = $amount . ' ' . $block['name'] . $plural;
$diff -= $amount * $block['amount'];
$current_level++;
}
}
return implode(' ', $result) . ' ago';
}
/**
* Returns where clause for loading correct revision for a given page
*
* @param int $page_id
* @param int $live_revision_number
* @param string $table_name
* @return string
*/
- function getRevsionWhereClause($page_id, $live_revision_number, $table_name = '')
+ public function getRevsionWhereClause($page_id, $live_revision_number, $table_name = '')
{
$revision = (int)$this->Application->GetVar('revision');
list ($user_id, $has_permission) = $this->getHistoryPermissionAndUser($page_id);
if ( $has_permission && $revision ) {
$revision_clause = $table_name . 'RevisionNumber = ' . $revision . ' AND ' . $table_name . 'IsDraft = 0';
}
else {
$editing_mode = $this->Application->GetVar('editing_mode'); // not in a EDITING_MODE constant, while in admin console
$revision_clause = $table_name . 'RevisionNumber = ' . $live_revision_number . ' AND ' . $table_name . 'IsDraft = 0';
if ( $this->Application->GetVar('preview') || $editing_mode == EDITING_MODE_CONTENT ) {
$revision_clause = '(' . $table_name . 'CreatedById = ' . $user_id . ' AND ' . $table_name . 'IsDraft = 1) OR (' . $revision_clause . ')';
}
}
return $revision_clause;
}
/**
- * Returns current admin user id (even, when called from front-end) and it's revision history view permission
- *
- * @param int $page_id
- * @return Array
- */
- function getHistoryPermissionAndUser($page_id)
- {
- $user_id = (int)$this->Application->RecallVar($this->Application->isAdmin ? 'user_id' : 'admin_user_id');
- $history_permission = $this->Application->CheckAdminPermission('CATEGORY.REVISION.HISTORY.VIEW', 0, $page_id);
-
- return Array ($user_id, $history_permission);
- }
-
- /**
* Creates new content block in every revision that misses it. Plus creates first page revision
*
* @param int $page_id
* @param int $num
*/
- function createNewContentBlock($page_id, $num)
+ public function createNewContentBlock($page_id, $num)
{
$sql = 'SELECT pc.PageContentId, pr.RevisionId
FROM ' . TABLE_PREFIX . 'PageRevisions pr
LEFT JOIN ' . TABLE_PREFIX . 'PageContent pc ON pc.RevisionId = pr.RevisionId AND pc.ContentNum = ' . $num . '
WHERE pr.PageId = ' . $page_id;
$revisions = $this->Conn->GetCol($sql, 'RevisionId');
if ( !$revisions ) {
// no revisions for a page -> create a live revision
$revision = $this->Application->recallObject('page-revision.live', null, Array ('skip_autoload' => true));
/* @var $revision kDBItem */
$revision->SetDBField('PageId', $page_id);
$revision->SetDBField('RevisionNumber', 1);
$revision->SetDBField('Status', STATUS_ACTIVE);
$revision->Create();
$revisions[ $revision->GetID() ] = NULL;
}
$content_block = $this->Application->recallObject('content.new', null, Array ('skip_autoload' => true));
/* @var $content_block kDBItem */
$content_block->SetDBField('PageId', $page_id);
$content_block->SetDBField('ContentNum', $num);
foreach ($revisions as $revision_id => $content_block_id) {
if ( is_numeric($content_block_id) ) {
continue;
}
$content_block->SetDBField('RevisionId', $revision_id);
$content_block->Create();
}
}
/**
* Loads content block by it's number
*
* @param kDBItem $content_block
* @param CategoriesItem $page
* @param int $num
*
* @return bool
*/
- function loadContentBlock(&$content_block, &$page, $num)
+ public function loadContentBlock(&$content_block, &$page, $num)
{
$page_id = $page->GetID();
if ( !EDITING_MODE && !$this->Application->GetVar('preview') ) {
$revision_clause = 'pr.RevisionNumber = ' . $page->GetDBField('LiveRevisionNumber') . ' AND pr.IsDraft = 0';
}
else {
$revision_clause = $this->getRevsionWhereClause($page_id, $page->GetDBField('LiveRevisionNumber'), 'pr.');
}
$sql = $content_block->GetSelectSQL() . '
WHERE (' . $content_block->TableName . '.PageId = ' . $page_id . ') AND (' . $content_block->TableName . '.ContentNum = ' . $num . ') AND (' . $revision_clause . ')
ORDER BY pr.IsDraft DESC, pr.RevisionNumber DESC';
$content_data = $this->Conn->GetRow($sql);
$content_block->LoadFromHash($content_data);
return $content_block->isLoaded();
}
}
Index: branches/5.3.x/core/units/content/content_eh.php
===================================================================
--- branches/5.3.x/core/units/content/content_eh.php (revision 15945)
+++ branches/5.3.x/core/units/content/content_eh.php (revision 15946)
@@ -1,260 +1,273 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class ContentEventHandler extends kDBEventHandler {
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent $event)
{
$perm_helper = $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$user_id = $this->Application->RecallVar('user_id');
// user can change top category
$top_category = $this->Application->getBaseCategory();
$perm_status = $perm_helper->CheckUserPermission($user_id, 'CATEGORY.MODIFY', 0, $top_category);
return $perm_helper->finalizePermissionCheck($event, $perm_status);
}
/**
* Saves changes to a content block (+ creates draft if missing)
*
* @param kEvent $event
*/
function OnSaveContentBlock($event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return ;
+
+ return;
}
- if ( !$this->saveContentBlock($event, false) ) {
+ $updated = $this->saveContentBlock($event, false);
+
+ if ( $this->Application->GetVar('ajax') == 'yes' ) {
+ $event->status = kEvent::erSTOP;
+ echo ($updated === false) ? 'FAILED' : 'OK';
+ }
+ elseif ( !$updated ) {
$event->status = kEvent::erFAIL;
}
$event->SetRedirectParam('opener', 'u');
}
/**
* Prepare temp tables and populate it
* with items selected in the grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnEdit(kEvent $event)
{
parent::OnEdit($event);
$fck_helper = $this->Application->recallObject('FCKHelper');
/* @var $fck_helper fckFCKHelper */
$transit_params = $fck_helper->getTransitParams();
foreach ($transit_params as $param_name => $param_value) {
$event->SetRedirectParam($param_name, kUtil::escape($param_value, kUtil::ESCAPE_URL));
}
}
/**
* Saves changes & changes language
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPreSaveAndChangeLanguage(kEvent $event)
{
if ( $this->UseTempTables($event) ) {
parent::OnPreSaveAndChangeLanguage($event);
return;
}
// CUSTOM: begin
$event->CallSubEvent('OnSaveContentBlock');
$event->SetRedirectParam('opener', 's');
// CUSTOM: end
if ( $event->status == kEvent::erSUCCESS ) {
$this->Application->SetVar('m_lang', $this->Application->GetVar('language'));
$data = $this->Application->GetVar('st_id');
if ( $data ) {
$event->SetRedirectParam('st_id', $data);
}
}
}
/**
* Performs auto-save of current content block (will create draft too)
*
* @param kEvent $event
*/
function OnAutoSave($event)
{
$event->status = kEvent::erSTOP;
if ( $this->Application->GetVar('ajax') != 'yes' ) {
return ;
}
echo $this->saveContentBlock($event, true);
}
/**
* Saves content block
*
* @param kEvent $event
* @param bool $is_draft
* @return string
*/
function saveContentBlock($event, $is_draft)
{
- $object = $event->getObject( Array('skip_autoload' => true) );
- /* @var $object kDBItem */
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ( !$items_info ) {
return '';
}
list ($object, $revision) = $this->getContentBlockAndRevision($event);
/* @var $revision kDBItem */
+ /* @var $object kDBItem */
list (, $field_values) = each($items_info);
$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
$updated = $object->Update();
if ( $updated ) {
$revision->SetDBField('AutoSavedOn_date', time());
- $revision->SetDBField('AutoSavedOn_time', time());
- $revision->Update();
+ $revision->SetDBField('AutoSavedOn_time', time());
+ $revision->Update();
}
if ( $is_draft ) {
if ( $updated ) {
- $page_helper = $this->Application->recallObject('PageHelper');
- /* @var $page_helper PageHelper */
+ $page_helper = $this->Application->recallObject('PageHelper');
+ /* @var $page_helper PageHelper */
- return $revision->GetField('AutoSavedOn') . ' (' . $page_helper->getAgoTime( $revision->GetDBField('AutoSavedOn') ) . ')';
- }
+ return $revision->GetField('AutoSavedOn') . ' (' . $page_helper->getAgoTime($revision->GetDBField('AutoSavedOn')) . ')';
+ }
}
else {
return $updated;
}
return '';
}
/**
* Returns last autosave time
*
* @param kEvent $event
*/
function OnGetAutoSaveTime($event)
{
$event->status = kEvent::erSTOP;
if ( $this->Application->GetVar('ajax') != 'yes' ) {
- return ;
+ return;
}
- list ($object, $revision) = $this->getContentBlockAndRevision($event);
+ list (, $revision) = $this->getContentBlockAndRevision($event);
/* @var $revision kDBItem */
$page_helper = $this->Application->recallObject('PageHelper');
- /* @var $page_helper PageHelper */
+ /* @var $page_helper PageHelper */
- $time = $revision->GetField('AutoSavedOn');
+ $time = $revision->GetField('AutoSavedOn');
- if ( $time ) {
- echo $time . ' (' . $page_helper->getAgoTime( $revision->GetDBField('AutoSavedOn') ) . ')';
- }
+ if ( $time ) {
+ echo $time . ' (' . $page_helper->getAgoTime($revision->GetDBField('AutoSavedOn')) . ')';
+ }
}
/**
* Loads content block from given revision
*
* @param kDBItem $object
* @param kDBItem $revision
*/
function loadFromRevision(&$object, &$revision)
{
- $load_keys = Array (
+ $load_keys = Array(
'PageId' => $object->GetDBField('PageId'),
'ContentNum' => $object->GetDBField('ContentNum'),
'RevisionId' => $revision->GetID(),
);
$object->Load($load_keys);
}
+ /**
+ * Returns content block.
+ *
+ * @param kEvent $event
+ *
+ * @return kDBItem[]
+ */
function getContentBlockAndRevision(kEvent $event)
{
- $object = $event->getObject( Array('skip_autoload' => true) );
+ $object = $event->getObject(Array('skip_autoload' => true));
/* @var $object kDBItem */
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ( !$items_info ) {
- return ;
+ return array();
}
- list ($id, $field_values) = each($items_info);
+ list ($id,) = each($items_info);
$object->Load($id);
- $revision = $this->Application->recallObject('page-revision', null, Array ('skip_autoload' => true));
+ $revision = $this->Application->recallObject('page-revision', null, Array('skip_autoload' => true));
/* @var $revision kDBItem */
- $revision->Load( $object->GetDBField('RevisionId') );
+ $revision->Load($object->GetDBField('RevisionId'));
if ( $this->Application->ConfigValue('EnablePageContentRevisionControl') && !$revision->GetDBField('IsDraft') ) {
// editing live revision of a page's content block -> get draft for current user and page
- $load_keys = Array (
+ $load_keys = Array(
'PageId' => $revision->GetDBField('PageId'),
'IsDraft' => 1,
'CreatedById' => $this->Application->RecallVar('user_id'),
);
$revision->Load($load_keys);
if ( $revision->isLoaded() ) {
// draft found -> use draft's content block version
$this->loadFromRevision($object, $revision);
}
else {
// draft not found -> create new
$revision->SetDBFieldsFromHash($load_keys);
$revision->SetDBField('FromRevisionId', $object->GetDBField('RevisionId'));
if ( $revision->Create() ) {
$this->loadFromRevision($object, $revision);
}
}
}
- return Array (&$object, &$revision);
+ return Array(&$object, &$revision);
}
}
\ No newline at end of file
Index: branches/5.3.x/core/ckeditor/plugins/my_document/images/document.png
===================================================================
Binary files branches/5.3.x/core/ckeditor/plugins/my_document/images/document.png (nonexistent) and branches/5.3.x/core/ckeditor/plugins/my_document/images/document.png (revision 15946) differ
Index: branches/5.3.x/core/ckeditor/plugins/my_document/plugin.js
===================================================================
--- branches/5.3.x/core/ckeditor/plugins/my_document/plugin.js (revision 15945)
+++ branches/5.3.x/core/ckeditor/plugins/my_document/plugin.js (revision 15946)
@@ -1,74 +1,74 @@
(
function() {
CKEDITOR.plugins.add(
'my_document',
{
init: function(editor) {
var pluginName = 'my_document';
CKEDITOR.dialog.add(pluginName, this.path + 'dialogs/document.js');
editor.addCommand(pluginName, new CKEDITOR.dialogCommand(pluginName));
editor.ui.addButton('Document',
{
label: 'Insert/Edit Document',
command: pluginName,
- icon: CKEDITOR.plugins.getPath(pluginName) + 'images/document.gif'
+ icon: this.path + 'images/document.png'
}
);
if (editor.addMenuItem) {
// A group menu is required
// order, as second parameter, is not required
editor.addMenuGroup(pluginName);
// Create a manu item
editor.addMenuItem(
'editDocument',
{
label: 'Document Properties',
command: pluginName,
icon: CKEDITOR.plugins.getPath(pluginName) + 'images/document.gif',
group: pluginName
}
);
}
if (editor.contextMenu) {
editor.contextMenu.addListener(
function(element, selection) { //function to be run when context menu is displayed
if ( !element ) {
return null;
}
var bInsideLink = ( element.is('a') || element.hasAscendant('a') ) ;
if ( bInsideLink || editor.getCommand( 'unlink' ).state != CKEDITOR.TRISTATE_DISABLED ) {
// Go up to the anchor to test its properties
var oLink = element.is('a') ? element : element.getParent();
var bIsAnchor = ( oLink && oLink.getAttribute('name') && !oLink.getAttribute('href') ) ;
// If it isn't a link then don't add the Link context menu
if ( !bIsAnchor && bInsideLink ) {
var id = oLink.getAttribute( 'id' , 2 );
if ( id && id.match(/^Doc_+/) ) {
return { editDocument: CKEDITOR.TRISTATE_OFF };
}
}
}
return null;
}
);
}
}
}
);
// some code here
}
)();
\ No newline at end of file
Index: branches/5.3.x/core/ckeditor/plugins/my_inline/images/cancel.png
===================================================================
Binary files branches/5.3.x/core/ckeditor/plugins/my_inline/images/cancel.png (nonexistent) and branches/5.3.x/core/ckeditor/plugins/my_inline/images/cancel.png (revision 15946) differ
Index: branches/5.3.x/core/ckeditor/plugins/my_inline/plugin.js
===================================================================
--- branches/5.3.x/core/ckeditor/plugins/my_inline/plugin.js (nonexistent)
+++ branches/5.3.x/core/ckeditor/plugins/my_inline/plugin.js (revision 15946)
@@ -0,0 +1,41 @@
+
+(function()
+{
+ CKEDITOR.plugins.add( 'my_inline', {
+ init: function (editor) {
+ var lang = editor.lang;
+
+ editor.addCommand('inline-save', {
+ modes: { wysiwyg: 1, source: 1 },
+ editorFocus: false,
+ exec: function () {
+ $(editor.element.$).data('no_save_on_blur', null).trigger('blur');
+ editor.focusManager.blur();
+ },
+ canUndo: false
+ });
+
+ editor.addCommand('inline-cancel', {
+ modes: { wysiwyg: 1, source: 1 },
+ editorFocus: false,
+ exec: function () {
+ $(editor.element.$).data('no_save_on_blur', true).trigger('blur');
+ editor.focusManager.blur();
+ },
+ canUndo: false
+ });
+
+ editor.ui.addButton('InlineSave', {
+ label: lang.save.toolbar,
+ command: 'inline-save',
+ icon: 'save'
+ });
+
+ editor.ui.addButton('InlineCancel', {
+ label: lang.common.close,
+ command: 'inline-cancel',
+ icon: this.path + 'images/cancel.png'
+ });
+ }
+ } );
+})();
Property changes on: branches/5.3.x/core/ckeditor/plugins/my_inline/plugin.js
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+LF
\ No newline at end of property
Index: branches/5.3.x/core/ckeditor/plugins/my_link/plugin.js
===================================================================
--- branches/5.3.x/core/ckeditor/plugins/my_link/plugin.js (revision 15945)
+++ branches/5.3.x/core/ckeditor/plugins/my_link/plugin.js (revision 15946)
@@ -1,703 +1,703 @@
(
function() {
CKEDITOR.plugins.add('my_link');
CKEDITOR.on(
'dialogDefinition',
function(ev) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
var editor = this;
if (dialogName == 'link') {
var plugin = CKEDITOR.plugins.link;
var $internal_page_mapping = {}; // mapping between @@PAGE_ID@@ and real url (for anchor loading)
var load_page_anchors = function ($page_id, dialog) {
var $url = $internal_page_mapping[$page_id];
var $tmp_iframe = $('#tmp_iframe');
var $internal_page_anchors = dialog.getContentElement( 'info', 'internalPageAnchors' );
var $current_anchor = $('#' + $internal_page_anchors.domId).data('anchor');
$internal_page_anchors.clear();
$internal_page_anchors.add( 'Loading ...', '' );
if ( $tmp_iframe.length == 0 ) {
$tmp_iframe = $('<iframe width="0" height="0" id="tmp_iframe"></iframe>').appendTo('body');
$tmp_iframe.get(0).onload = function () {
var $anchors = $('a[name]', $tmp_iframe.get(0).contentWindow.document);
$internal_page_anchors.allowOnChange = false;
$internal_page_anchors.clear();
$internal_page_anchors.add( $anchors.length > 0 ? '' : '(No anchors available in the document)', '' );
$anchors.each(
function () {
$internal_page_anchors.add( $(this).attr('name') );
}
);
$internal_page_anchors.setValue($current_anchor);
$internal_page_anchors.allowOnChange = true;
}
}
$tmp_iframe.attr('src', $internal_page_mapping[$page_id]);
}
// Handles the event when the "Type" selection box is changed.
var linkTypeChanged = function()
{
var dialog = this.getDialog(),
partIds = [ 'internalOptions', 'urlOptions', 'anchorOptions', 'emailOptions' ],
typeValue = this.getValue(),
uploadTab = dialog.definition.getContents( 'upload' ),
uploadInitiallyHidden = uploadTab && uploadTab.hidden;
switch ( typeValue ) {
case 'url':
if ( editor.config.linkShowTargetTab )
dialog.showPage( 'target' );
if ( !uploadInitiallyHidden )
dialog.showPage( 'upload' );
break;
case 'internal':
if ( editor.config.linkShowTargetTab )
dialog.showPage( 'target' );
if ( !uploadInitiallyHidden )
dialog.hidePage( 'upload' );
// select internal page according to link url (on link type change)
var $url = dialog.getContentElement('info', 'url').getValue();
if ( $internal_page_mapping[$url] !== undefined ) {
dialog.getContentElement('info', 'internal_page').setValue($url);
}
break;
default:
dialog.hidePage( 'target' );
if ( !uploadInitiallyHidden )
dialog.hidePage( 'upload' );
break;
}
for ( var i = 0 ; i < partIds.length ; i++ )
{
var element = dialog.getContentElement( 'info', partIds[i] );
if ( !element )
continue;
element = element.getElement().getParent().getParent();
if ( partIds[i] == typeValue + 'Options' )
element.show();
else
element.hide();
}
dialog.layout();
};
var javascriptProtocolRegex = /^javascript:/,
emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/,
emailSubjectRegex = /subject=([^;?:@&=$,\/]*)/,
emailBodyRegex = /body=([^;?:@&=$,\/]*)/,
anchorRegex = /^#(.*)$/,
urlRegex = /^((?:http|https|ftp|news):\/\/)?(.*)$/,
selectableTargets = /^(_(?:self|top|parent|blank))$/,
encodedEmailLinkRegex = /^javascript:void\(location\.href='mailto:'\+String\.fromCharCode\(([^)]+)\)(?:\+'(.*)')?\)$/,
functionCallProtectedEmailLinkRegex = /^javascript:([^(]+)\(([^)]+)\)$/,
internalPageRegex = /^@@[\d]+@@(#.*$|$)/; // CUSTOM
var popupRegex =
/\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/;
var popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/gi;
var parseLink = function( editor, element )
{
var href = ( element && ( element.data( 'cke-saved-href' ) || element.getAttribute( 'href' ) ) ) || '',
javascriptMatch,
emailMatch,
anchorMatch,
urlMatch,
retval = {};
if ( ( javascriptMatch = href.match( javascriptProtocolRegex ) ) )
{
var emailProtection = editor.config.emailProtection || '';
if ( emailProtection == 'encode' )
{
href = href.replace( encodedEmailLinkRegex,
function ( match, protectedAddress, rest )
{
return 'mailto:' +
String.fromCharCode.apply( String, protectedAddress.split( ',' ) ) +
( rest && unescapeSingleQuote( rest ) );
});
}
// Protected email link as function call.
else if ( emailProtection )
{
href.replace( functionCallProtectedEmailLinkRegex, function( match, funcName, funcArgs )
{
if ( funcName == compiledProtectionFunction.name )
{
retval.type = 'email';
var email = retval.email = {};
var paramRegex = /[^,\s]+/g,
paramQuoteRegex = /(^')|('$)/g,
paramsMatch = funcArgs.match( paramRegex ),
paramsMatchLength = paramsMatch.length,
paramName,
paramVal;
for ( var i = 0; i < paramsMatchLength; i++ )
{
paramVal = decodeURIComponent( unescapeSingleQuote( paramsMatch[ i ].replace( paramQuoteRegex, '' ) ) );
paramName = compiledProtectionFunction.params[ i ].toLowerCase();
email[ paramName ] = paramVal;
}
email.address = [ email.name, email.domain ].join( '@' );
}
} );
}
}
if ( !retval.type )
{
if ( ( anchorMatch = href.match( anchorRegex ) ) )
{
retval.type = 'anchor';
retval.anchor = {};
retval.anchor.name = retval.anchor.id = anchorMatch[1];
}
// Protected email link as encoded string.
else if ( ( emailMatch = href.match( emailRegex ) ) )
{
var subjectMatch = href.match( emailSubjectRegex ),
bodyMatch = href.match( emailBodyRegex );
retval.type = 'email';
var email = ( retval.email = {} );
email.address = emailMatch[ 1 ];
subjectMatch && ( email.subject = decodeURIComponent( subjectMatch[ 1 ] ) );
bodyMatch && ( email.body = decodeURIComponent( bodyMatch[ 1 ] ) );
}
// CUSTOM: begin
else if ( href && href.match( internalPageRegex ) )
{
retval.type = 'internal';
retval.url = {};
retval.url.protocol = '';
retval.anchor = {};
if ( href.match(/^(.*)#(.*)$/) ) {
retval.url.url = RegExp.$1;
retval.internal_anchor = RegExp.$2;
}
else {
retval.url.url = href;
retval.internal_anchor = '';
}
}
// CUSTOM: end
// urlRegex matches empty strings, so need to check for href as well.
else if ( href && ( urlMatch = href.match( urlRegex ) ) )
{
retval.type = 'url';
retval.url = {};
retval.url.protocol = urlMatch[1];
retval.url.url = urlMatch[2];
}
// CUSTOM: begin
else {
retval.type = 'internal';
retval.url = {};
retval.url.protocol = '';
retval.url.url = '';
retval.internal_anchor = '';
}
// CUSTOM: end
}
// Load target and popup settings.
if ( element )
{
var target = element.getAttribute( 'target' );
retval.target = {};
retval.adv = {};
// IE BUG: target attribute is an empty string instead of null in IE if it's not set.
if ( !target )
{
var onclick = element.data( 'cke-pa-onclick' ) || element.getAttribute( 'onclick' ),
onclickMatch = onclick && onclick.match( popupRegex );
if ( onclickMatch )
{
retval.target.type = 'popup';
retval.target.name = onclickMatch[1];
var featureMatch;
while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[2] ) ) )
{
// Some values should remain numbers (#7300)
if ( ( featureMatch[2] == 'yes' || featureMatch[2] == '1' ) && !( featureMatch[1] in { height:1, width:1, top:1, left:1 } ) )
retval.target[ featureMatch[1] ] = true;
else if ( isFinite( featureMatch[2] ) )
retval.target[ featureMatch[1] ] = featureMatch[2];
}
}
}
else
{
var targetMatch = target.match( selectableTargets );
if ( targetMatch )
retval.target.type = retval.target.name = target;
else
{
retval.target.type = 'frame';
retval.target.name = target;
}
}
var me = this;
var advAttr = function( inputName, attrName )
{
var value = element.getAttribute( attrName );
if ( value !== null )
retval.adv[ inputName ] = value || '';
};
advAttr( 'advId', 'id' );
advAttr( 'advLangDir', 'dir' );
advAttr( 'advAccessKey', 'accessKey' );
retval.adv.advName =
element.data( 'cke-saved-name' )
|| element.getAttribute( 'name' )
|| '';
advAttr( 'advLangCode', 'lang' );
advAttr( 'advTabIndex', 'tabindex' );
advAttr( 'advTitle', 'title' );
advAttr( 'advContentType', 'type' );
advAttr( 'advCSSClasses', 'class' );
advAttr( 'advCharset', 'charset' );
advAttr( 'advStyles', 'style' );
advAttr( 'advRel', 'rel' );
}
// Find out whether we have any anchors in the editor.
// Get all IMG elements in CK document.
var elements = editor.document.getElementsByTag( 'img' ),
realAnchors = new CKEDITOR.dom.nodeList( editor.document.$.anchors ),
anchors = retval.anchors = [];
for ( var i = 0; i < elements.count() ; i++ )
{
var item = elements.getItem( i );
if ( item.data( 'cke-realelement' ) && item.data( 'cke-real-element-type' ) == 'anchor' )
anchors.push( editor.restoreRealElement( item ) );
}
for ( i = 0 ; i < realAnchors.count() ; i++ )
anchors.push( realAnchors.getItem( i ) );
for ( i = 0 ; i < anchors.length ; i++ )
{
item = anchors[ i ];
anchors[ i ] = { name : item.getAttribute( 'name' ), id : item.getAttribute( 'id' ) };
}
// Record down the selected element in the dialog.
this._.selectedElement = element;
return retval;
};
var infoTab = dialogDefinition.getContents( 'info' );
var linkType = infoTab.get('linkType');
linkType['items'].unshift( ['Internal Web Page', 'internal'] );
linkType['default'] = 'internal';
linkType['onChange'] = linkTypeChanged;
infoTab.add(
{
type : 'vbox',
id : 'internalOptions',
children :
[
{
type : 'select',
id : 'internal_page',
label : 'Internal Page Name',
items : [
[ '' ]
],
onChange: function ( ) {
// place internal page ID from this dropdown into URL field of the dialog
var dialog = this.getDialog();
this.allowOnChange = false;
dialog.getContentElement('info', 'url').setValue( this.getValue() );
this.allowOnChange = true;
load_page_anchors( this.getValue(), dialog );
},
setup : function( data ) {
var $me = this;
var $link_url = data.url.url;
var $ajax_url = CKEDITOR.basePath.replace( /core.*$/, 'admin/index.php?events[fck]=OnLoadCmsTree&admin=1' );
var $internal_page_anchors = this.getDialog().getContentElement( 'info', 'internalPageAnchors' );
$('#' + $internal_page_anchors.domId).data('anchor', data.internal_anchor);
$.ajax(
{
type: 'GET',
url: $ajax_url,
async: false,
success: function ($xml) {
$me.allowOnChange = false;
$me.clear();
$me.add( '' );
$('CmsPage', $xml).each(
function ($i) {
var $node = $(this);
var cms_id = $node.attr('st_id');
var cms_page = $node.attr('path');
var real_url = $node.attr('real_url');
$internal_page_mapping[cms_page] = real_url;
$me.add( $node.attr('title').replace(/&amp;/g, '&') , cms_page );
if ( $link_url && $link_url.match(cms_page + '$') ) {
$me.setValue(cms_page);
- load_page_anchors( cms_page, this.getDialog() );
+ load_page_anchors( cms_page, $me.getDialog() );
}
}
);
// undo CKEditor default "htmlspecialchars" on all HTML
$('option', '#' + $me.domId).each(
function ($index) {
var $option = $(this),
$level_indicator = '&mdash;',
$html = $option.html().replace(/&amp;/g, '&'),
$level = ($html.length - $html.replace(new RegExp($level_indicator, 'g'), '').length ) / $level_indicator.length;
if ( $html.match(/^(.*?) (.*?) (\(.*?\))$/) ) {
// "&mdash;&mdash; rss (news/rss.html)"
$level_indicator = RegExp.$1;
var $page_name = RegExp.$2,
$page_url = RegExp.$3;
$html = $level_indicator + ' ' + $page_name + ' ' + $page_url;
}
$option.html($html);
}
);
$me.allowOnChange = true;
$me.getDialog().layout();
},
dataType: 'xml'
}
);
var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
if ( linkType && linkType.getValue() == 'internal' ) {
this.focus();
}
},
},
{
type : 'select',
id : 'internalPageAnchors',
label : 'Select an Anchor',
items : [
[ '' ]
],
commit : function( data ) {
data.internal_anchor = this.getValue();
this.allowOnChange = false;
}
}
]
}
);
dialogDefinition['onShow'] = function() {
this.fakeObj = false;
var editor = this.getParentEditor(),
selection = editor.getSelection(),
element = null;
// Fill in all the relevant fields if there's already one link selected.
if ( ( element = plugin.getSelectedLink( editor ) ) && element.hasAttribute( 'href' ) )
selection.selectElement( element );
else if ( ( element = selection.getSelectedElement() ) && element.is( 'img' )
&& element.data( 'cke-real-element-type' )
&& element.data( 'cke-real-element-type' ) == 'anchor' )
{
this.fakeObj = element;
element = editor.restoreRealElement( this.fakeObj );
selection.selectElement( this.fakeObj );
}
else
element = null;
this.setupContent( parseLink.apply( this, [ editor, element ] ) );
};
dialogDefinition['onOk'] = function() {
var attributes = {},
removeAttributes = [],
data = {},
me = this,
editor = this.getParentEditor();
this.commitContent( data );
// Compose the URL.
switch ( data.type || 'internal' )
{
// CUSTOM: begin
case 'internal':
var url = ( data.url && data.url.url ) || '';
var anchor = data.internal_anchor || '';
attributes[ 'data-cke-saved-href' ] = url;
if ( anchor ) {
attributes[ 'data-cke-saved-href' ] += '#' + anchor;
}
break;
// CUSTOM: end
case 'url':
var protocol = ( data.url && data.url.protocol != undefined ) ? data.url.protocol : 'http://',
url = ( data.url && data.url.url ) || '';
attributes[ 'data-cke-saved-href' ] = ( url.indexOf( '/' ) === 0 ) ? url : protocol + url;
break;
case 'anchor':
var name = ( data.anchor && data.anchor.name ),
id = ( data.anchor && data.anchor.id );
attributes[ 'data-cke-saved-href' ] = '#' + ( name || id || '' );
break;
case 'email':
var linkHref,
email = data.email,
address = email.address,
emailProtection = editor.config.emailProtection || '';
switch( emailProtection )
{
case '' :
case 'encode' :
{
var subject = encodeURIComponent( email.subject || '' ),
body = encodeURIComponent( email.body || '' );
// Build the e-mail parameters first.
var argList = [];
subject && argList.push( 'subject=' + subject );
body && argList.push( 'body=' + body );
argList = argList.length ? '?' + argList.join( '&' ) : '';
if ( emailProtection == 'encode' )
{
linkHref = [ 'javascript:void(location.href=\'mailto:\'+',
protectEmailAddressAsEncodedString( address ) ];
// parameters are optional.
argList && linkHref.push( '+\'', escapeSingleQuote( argList ), '\'' );
linkHref.push( ')' );
}
else
linkHref = [ 'mailto:', address, argList ];
break;
}
default :
{
// Separating name and domain.
var nameAndDomain = address.split( '@', 2 );
email.name = nameAndDomain[ 0 ];
email.domain = nameAndDomain[ 1 ];
linkHref = [ 'javascript:', protectEmailLinkAsFunction( email ) ];
}
}
attributes[ 'data-cke-saved-href' ] = linkHref.join( '' );
break;
}
// Popups and target.
if ( data.target )
{
if ( data.target.type == 'popup' )
{
var onclickList = [ 'window.open(this.href, \'',
data.target.name || '', '\', \'' ];
var featureList = [ 'resizable', 'status', 'location', 'toolbar', 'menubar', 'fullscreen',
'scrollbars', 'dependent' ];
var featureLength = featureList.length;
var addFeature = function( featureName )
{
if ( data.target[ featureName ] )
featureList.push( featureName + '=' + data.target[ featureName ] );
};
for ( var i = 0 ; i < featureLength ; i++ )
featureList[i] = featureList[i] + ( data.target[ featureList[i] ] ? '=yes' : '=no' ) ;
addFeature( 'width' );
addFeature( 'left' );
addFeature( 'height' );
addFeature( 'top' );
onclickList.push( featureList.join( ',' ), '\'); return false;' );
attributes[ 'data-cke-pa-onclick' ] = onclickList.join( '' );
// Add the "target" attribute. (#5074)
removeAttributes.push( 'target' );
}
else
{
if ( data.target.type != 'notSet' && data.target.name )
attributes.target = data.target.name;
else
removeAttributes.push( 'target' );
removeAttributes.push( 'data-cke-pa-onclick', 'onclick' );
}
}
// Advanced attributes.
if ( data.adv )
{
var advAttr = function( inputName, attrName )
{
var value = data.adv[ inputName ];
if ( value )
attributes[attrName] = value;
else
removeAttributes.push( attrName );
};
advAttr( 'advId', 'id' );
advAttr( 'advLangDir', 'dir' );
advAttr( 'advAccessKey', 'accessKey' );
if ( data.adv[ 'advName' ] )
{
attributes[ 'name' ] = attributes[ 'data-cke-saved-name' ] = data.adv[ 'advName' ];
attributes[ 'class' ] = ( attributes[ 'class' ] ? attributes[ 'class' ] + ' ' : '' ) + 'cke_anchor';
}
else
removeAttributes = removeAttributes.concat( [ 'data-cke-saved-name', 'name' ] );
advAttr( 'advLangCode', 'lang' );
advAttr( 'advTabIndex', 'tabindex' );
advAttr( 'advTitle', 'title' );
advAttr( 'advContentType', 'type' );
advAttr( 'advCSSClasses', 'class' );
advAttr( 'advCharset', 'charset' );
advAttr( 'advStyles', 'style' );
advAttr( 'advRel', 'rel' );
}
// Browser need the "href" fro copy/paste link to work. (#6641)
attributes.href = attributes[ 'data-cke-saved-href' ];
if ( !this._.selectedElement )
{
// Create element if current selection is collapsed.
var selection = editor.getSelection(),
ranges = selection.getRanges( true );
if ( ranges.length == 1 && ranges[0].collapsed )
{
// Short mailto link text view (#5736).
var text = new CKEDITOR.dom.text( data.type == 'email' ?
data.email.address : attributes[ 'data-cke-saved-href' ], editor.document );
ranges[0].insertNode( text );
ranges[0].selectNodeContents( text );
selection.selectRanges( ranges );
}
// Apply style.
var style = new CKEDITOR.style( { element : 'a', attributes : attributes } );
style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.
style.apply( editor.document );
}
else
{
// We're only editing an existing link, so just overwrite the attributes.
var element = this._.selectedElement,
href = element.data( 'cke-saved-href' ),
textView = element.getHtml();
// IE BUG: Setting the name attribute to an existing link doesn't work.
// Must re-create the link from weired syntax to workaround.
if ( CKEDITOR.env.ie && !( CKEDITOR.document.$.documentMode >= 8 ) && attributes.name != element.getAttribute( 'name' ) )
{
var newElement = new CKEDITOR.dom.element( '<a name="' + CKEDITOR.tools.htmlEncode( attributes.name ) + '">',
editor.document );
selection = editor.getSelection();
element.copyAttributes( newElement, { name : 1 } );
element.moveChildren( newElement );
newElement.replace( element );
element = newElement;
selection.selectElement( element );
}
element.setAttributes( attributes );
element.removeAttributes( removeAttributes );
// Update text view when user changes protocol (#4612).
if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 )
{
// Short mailto link text view (#5736).
element.setHtml( data.type == 'email' ?
data.email.address : attributes[ 'data-cke-saved-href' ] );
}
// Make the element display as an anchor if a name has been set.
if ( element.getAttribute( 'name' ) )
element.addClass( 'cke_anchor' );
else
element.removeClass( 'cke_anchor' );
if ( this.fakeObj )
editor.createFakeElement( element, 'cke_anchor', 'anchor' ).replace( this.fakeObj );
delete this._.selectedElement;
}
};
}
}
);
}
)();
\ No newline at end of file
Index: branches/5.3.x/core/ckeditor/ckeditor_php5.php
===================================================================
--- branches/5.3.x/core/ckeditor/ckeditor_php5.php (revision 15945)
+++ branches/5.3.x/core/ckeditor/ckeditor_php5.php (revision 15946)
@@ -1,562 +1,599 @@
<?php
/*
* Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.html or http://ckeditor.com/license
*/
/**
* \brief CKEditor class that can be used to create editor
* instances in PHP pages on server side.
* @see http://ckeditor.com
*
* Sample usage:
* @code
* $CKEditor = new CKEditor();
* $CKEditor->editor("editor1", "<p>Initial value.</p>");
* @endcode
*/
class CKEditor
{
/**
* The version of %CKEditor.
*/
const version = '3.6.3';
/**
* A constant string unique for each release of %CKEditor.
*/
const timestamp = 'C3HA5RM';
/**
* URL to the %CKEditor installation directory (absolute or relative to document root).
* If not set, CKEditor will try to guess it's path.
*
* Example usage:
* @code
* $CKEditor->basePath = '/ckeditor/';
* @endcode
*/
public $basePath;
/**
* An array that holds the global %CKEditor configuration.
* For the list of available options, see http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
*
* Example usage:
* @code
* $CKEditor->config['height'] = 400;
* // Use @@ at the beggining of a string to ouput it without surrounding quotes.
* $CKEditor->config['width'] = '@@screen.width * 0.8';
* @endcode
*/
public $config = array();
/**
* A boolean variable indicating whether CKEditor has been initialized.
* Set it to true only if you have already included
* &lt;script&gt; tag loading ckeditor.js in your website.
*/
public $initialized = false;
/**
* Boolean variable indicating whether created code should be printed out or returned by a function.
*
* Example 1: get the code creating %CKEditor instance and print it on a page with the "echo" function.
* @code
* $CKEditor = new CKEditor();
* $CKEditor->returnOutput = true;
* $code = $CKEditor->editor("editor1", "<p>Initial value.</p>");
* echo "<p>Editor 1:</p>";
* echo $code;
* @endcode
*/
public $returnOutput = false;
/**
* An array with textarea attributes.
*
* When %CKEditor is created with the editor() method, a HTML &lt;textarea&gt; element is created,
* it will be displayed to anyone with JavaScript disabled or with incompatible browser.
*/
public $textareaAttributes = array( "rows" => 8, "cols" => 60 );
/**
* A string indicating the creation date of %CKEditor.
* Do not change it unless you want to force browsers to not use previously cached version of %CKEditor.
*/
public $timestamp = "C3HA5RM";
/**
* An array that holds event listeners.
*/
private $events = array();
/**
* An array that holds global event listeners.
*/
private $globalEvents = array();
public $lateLoad = false;
/**
* Main Constructor.
*
* @param $basePath (string) URL to the %CKEditor installation directory (optional).
*/
function __construct($basePath = null) {
if (!empty($basePath)) {
$this->basePath = $basePath;
}
}
/**
* Creates a %CKEditor instance.
* In incompatible browsers %CKEditor will downgrade to plain HTML &lt;textarea&gt; element.
*
* @param $name (string) Name of the %CKEditor instance (this will be also the "name" attribute of textarea element).
* @param $value (string) Initial value (optional).
* @param $config (array) The specific configurations to apply to this editor instance (optional).
* @param $events (array) Event listeners for this editor instance (optional).
*
* Example usage:
* @code
* $CKEditor = new CKEditor();
* $CKEditor->editor("field1", "<p>Initial value.</p>");
* @endcode
*
* Advanced example:
* @code
* $CKEditor = new CKEditor();
* $config = array();
* $config['toolbar'] = array(
* array( 'Source', '-', 'Bold', 'Italic', 'Underline', 'Strike' ),
* array( 'Image', 'Link', 'Unlink', 'Anchor' )
* );
* $events['instanceReady'] = 'function (ev) {
* alert("Loaded: " + ev.editor.name);
* }';
* $CKEditor->editor("field1", "<p>Initial value.</p>", $config, $events);
* @endcode
*/
public function editor($name, $value = "", $config = array(), $events = array())
{
$attr = "";
foreach ($this->textareaAttributes as $key => $val) {
$attr.= " " . $key . '="' . str_replace('"', '&quot;', $val) . '"';
}
$out = "<textarea name=\"" . $name . "\" id=\"" . $name . "\"" . $attr . ">" . htmlspecialchars($value) . "</textarea>\n";
if (!$this->initialized) {
$out .= $this->init();
}
$_config = $this->configSettings($config, $events);
$js = $this->returnGlobalEvents();
$json_config = !empty($_config) ? $this->jsEncode($_config) : '{}';
if ($this->lateLoad) {
$js .= "\$CKEditors[ '".$name."' ] = ".$json_config.";";
}
else {
$js .= "CKEDITOR.replace('".$name."', ".$json_config.");";
}
$out .= $this->script($js);
if (!$this->returnOutput) {
print $out;
$out = "";
}
return $out;
}
/**
* Replaces a &lt;textarea&gt; with a %CKEditor instance.
*
* @param $id (string) The id or name of textarea element.
* @param $config (array) The specific configurations to apply to this editor instance (optional).
* @param $events (array) Event listeners for this editor instance (optional).
*
* Example 1: adding %CKEditor to &lt;textarea name="article"&gt;&lt;/textarea&gt; element:
* @code
* $CKEditor = new CKEditor();
* $CKEditor->replace("article");
* @endcode
*/
public function replace($id, $config = array(), $events = array())
{
$out = "";
if (!$this->initialized) {
$out .= $this->init();
}
$_config = $this->configSettings($config, $events);
$js = $this->returnGlobalEvents();
- if (!empty($_config)) {
- $js .= "CKEDITOR.replace('".$id."', ".$this->jsEncode($_config).");";
+ $json_config = !empty($_config) ? $this->jsEncode($_config) : '{}';
+
+ if ($this->lateLoad) {
+ $js .= "\$CKEditors[ '".$id."' ] = ".$json_config.";";
}
else {
- $js .= "CKEDITOR.replace('".$id."');";
+ $js .= "CKEDITOR.replace('".$id."', ".$json_config.");";
+ }
+
+ $out .= $this->script($js);
+
+ if (!$this->returnOutput) {
+ print $out;
+ $out = "";
}
+
+ return $out;
+ }
+
+ /**
+ * Creates inline instance of editor.
+ *
+ * @param string $id The id or name of textarea element.
+ * @param array $config The specific configurations to apply to this editor instance (optional).
+ * @param array $events Event listeners for this editor instance (optional).
+ *
+ * @return string
+ */
+ public function inline($id, $config = array(), $events = array())
+ {
+ $out = "";
+ if (!$this->initialized) {
+ $out .= $this->init();
+ }
+
+ $_config = $this->configSettings($config, $events);
+
+ $js = $this->returnGlobalEvents();
+ $json_config = !empty($_config) ? $this->jsEncode($_config) : '{}';
+
+ $js .= "CKEDITOR.disableAutoInline = true;\n";
+ $js .= "CKEDITOR.inline('".$id."', ".$json_config.");";
+
$out .= $this->script($js);
if (!$this->returnOutput) {
print $out;
$out = "";
}
return $out;
}
/**
* Replace all &lt;textarea&gt; elements available in the document with editor instances.
*
* @param $className (string) If set, replace all textareas with class className in the page.
*
* Example 1: replace all &lt;textarea&gt; elements in the page.
* @code
* $CKEditor = new CKEditor();
* $CKEditor->replaceAll();
* @endcode
*
* Example 2: replace all &lt;textarea class="myClassName"&gt; elements in the page.
* @code
* $CKEditor = new CKEditor();
* $CKEditor->replaceAll( 'myClassName' );
* @endcode
*/
public function replaceAll($className = null)
{
$out = "";
if (!$this->initialized) {
$out .= $this->init();
}
$_config = $this->configSettings();
$js = $this->returnGlobalEvents();
if (empty($_config)) {
if (empty($className)) {
$js .= "CKEDITOR.replaceAll();";
}
else {
$js .= "CKEDITOR.replaceAll('".$className."');";
}
}
else {
$classDetection = "";
$js .= "CKEDITOR.replaceAll( function(textarea, config) {\n";
if (!empty($className)) {
$js .= " var classRegex = new RegExp('(?:^| )' + '". $className ."' + '(?:$| )');\n";
$js .= " if (!classRegex.test(textarea.className))\n";
$js .= " return false;\n";
}
$js .= " CKEDITOR.tools.extend(config, ". $this->jsEncode($_config) .", true);";
$js .= "} );";
}
$out .= $this->script($js);
if (!$this->returnOutput) {
print $out;
$out = "";
}
return $out;
}
/**
* Adds event listener.
* Events are fired by %CKEditor in various situations.
*
* @param $event (string) Event name.
* @param $javascriptCode (string) Javascript anonymous function or function name.
*
* Example usage:
* @code
* $CKEditor->addEventHandler('instanceReady', 'function (ev) {
* alert("Loaded: " + ev.editor.name);
* }');
* @endcode
*/
public function addEventHandler($event, $javascriptCode)
{
if (!isset($this->events[$event])) {
$this->events[$event] = array();
}
// Avoid duplicates.
if (!in_array($javascriptCode, $this->events[$event])) {
$this->events[$event][] = $javascriptCode;
}
}
/**
* Clear registered event handlers.
* Note: this function will have no effect on already created editor instances.
*
* @param $event (string) Event name, if not set all event handlers will be removed (optional).
*/
public function clearEventHandlers($event = null)
{
if (!empty($event)) {
$this->events[$event] = array();
}
else {
$this->events = array();
}
}
/**
* Adds global event listener.
*
* @param $event (string) Event name.
* @param $javascriptCode (string) Javascript anonymous function or function name.
*
* Example usage:
* @code
* $CKEditor->addGlobalEventHandler('dialogDefinition', 'function (ev) {
* alert("Loading dialog: " + ev.data.name);
* }');
* @endcode
*/
public function addGlobalEventHandler($event, $javascriptCode)
{
if (!isset($this->globalEvents[$event])) {
$this->globalEvents[$event] = array();
}
// Avoid duplicates.
if (!in_array($javascriptCode, $this->globalEvents[$event])) {
$this->globalEvents[$event][] = $javascriptCode;
}
}
/**
* Clear registered global event handlers.
* Note: this function will have no effect if the event handler has been already printed/returned.
*
* @param $event (string) Event name, if not set all event handlers will be removed (optional).
*/
public function clearGlobalEventHandlers($event = null)
{
if (!empty($event)) {
$this->globalEvents[$event] = array();
}
else {
$this->globalEvents = array();
}
}
/**
* Prints javascript code.
*
* @param string $js
*/
private function script($js)
{
$out = "<script type=\"text/javascript\">";
$out .= "//<![CDATA[\n";
$out .= $js;
$out .= "\n//]]>";
$out .= "</script>\n";
return $out;
}
/**
* Returns the configuration array (global and instance specific settings are merged into one array).
*
* @param $config (array) The specific configurations to apply to editor instance.
* @param $events (array) Event listeners for editor instance.
*/
private function configSettings($config = array(), $events = array())
{
$_config = $this->config;
$_events = $this->events;
if (is_array($config) && !empty($config)) {
$_config = array_merge($_config, $config);
}
if (is_array($events) && !empty($events)) {
foreach ($events as $eventName => $code) {
if (!isset($_events[$eventName])) {
$_events[$eventName] = array();
}
if (!in_array($code, $_events[$eventName])) {
$_events[$eventName][] = $code;
}
}
}
if (!empty($_events)) {
foreach($_events as $eventName => $handlers) {
if (empty($handlers)) {
continue;
}
else if (count($handlers) == 1) {
$_config['on'][$eventName] = '@@'.$handlers[0];
}
else {
$_config['on'][$eventName] = '@@function (ev){';
foreach ($handlers as $handler => $code) {
$_config['on'][$eventName] .= '('.$code.')(ev);';
}
$_config['on'][$eventName] .= '}';
}
}
}
return $_config;
}
/**
* Return global event handlers.
*/
private function returnGlobalEvents()
{
static $returnedEvents;
$out = "";
if (!isset($returnedEvents)) {
$returnedEvents = array();
}
if (!empty($this->globalEvents)) {
foreach ($this->globalEvents as $eventName => $handlers) {
foreach ($handlers as $handler => $code) {
if (!isset($returnedEvents[$eventName])) {
$returnedEvents[$eventName] = array();
}
// Return only new events
if (!in_array($code, $returnedEvents[$eventName])) {
$out .= ($code ? "\n" : "") . "CKEDITOR.on('". $eventName ."', $code);";
$returnedEvents[$eventName][] = $code;
}
}
}
}
return $out;
}
/**
* Initializes CKEditor (executed only once).
*/
private function init()
{
static $initComplete;
$out = "";
if (!empty($initComplete)) {
return "";
}
if ($this->initialized) {
$initComplete = true;
return "";
}
$args = "";
$ckeditorPath = $this->ckeditorPath();
if (!empty($this->timestamp) && $this->timestamp != "%"."TIMESTAMP%") {
$args = '?t=' . $this->timestamp;
}
// Skip relative paths...
if (strpos($ckeditorPath, '..') !== 0) {
$out .= $this->script("window.CKEDITOR_BASEPATH='". $ckeditorPath ."';");
}
$out .= "<script type=\"text/javascript\" src=\"" . $ckeditorPath . 'ckeditor.js' . $args . "\"></script>\n";
$extraCode = "";
if ($this->timestamp != self::timestamp) {
$extraCode .= ($extraCode ? "\n" : "") . "CKEDITOR.timestamp = '". $this->timestamp ."';";
}
if ($extraCode) {
$out .= $this->script($extraCode);
}
$initComplete = $this->initialized = true;
return $out;
}
/**
* Return path to ckeditor.js.
*/
private function ckeditorPath()
{
if (!empty($this->basePath)) {
return $this->basePath;
}
/**
* The absolute pathname of the currently executing script.
* Note: If a script is executed with the CLI, as a relative path, such as file.php or ../file.php,
* $_SERVER['SCRIPT_FILENAME'] will contain the relative path specified by the user.
*/
if (isset($_SERVER['SCRIPT_FILENAME'])) {
$realPath = dirname($_SERVER['SCRIPT_FILENAME']);
}
else {
/**
* realpath - Returns canonicalized absolute pathname
*/
$realPath = realpath( './' ) ;
}
/**
* The filename of the currently executing script, relative to the document root.
* For instance, $_SERVER['PHP_SELF'] in a script at the address http://example.com/test.php/foo.bar
* would be /test.php/foo.bar.
*/
$selfPath = dirname($_SERVER['PHP_SELF']);
$file = str_replace("\\", "/", __FILE__);
if (!$selfPath || !$realPath || !$file) {
return "/ckeditor/";
}
$documentRoot = substr($realPath, 0, strlen($realPath) - strlen($selfPath));
$fileUrl = substr($file, strlen($documentRoot));
$ckeditorUrl = str_replace("ckeditor_php5.php", "", $fileUrl);
return $ckeditorUrl;
}
/**
* This little function provides a basic JSON support.
*
* @param mixed $val
* @return string
*/
private function jsEncode($val)
{
if (is_null($val)) {
return 'null';
}
if (is_bool($val)) {
return $val ? 'true' : 'false';
}
if (is_int($val)) {
return $val;
}
if (is_float($val)) {
return str_replace(',', '.', $val);
}
if (is_array($val) || is_object($val)) {
if (is_array($val) && (array_keys($val) === range(0,count($val)-1))) {
return '[' . implode(',', array_map(array($this, 'jsEncode'), $val)) . ']';
}
$temp = array();
foreach ($val as $k => $v){
$temp[] = $this->jsEncode("{$k}") . ':' . $this->jsEncode($v);
}
return '{' . implode(',', $temp) . '}';
}
// String otherwise
if (strpos($val, '@@') === 0)
return substr($val, 2);
if (strtoupper(substr($val, 0, 9)) == 'CKEDITOR.')
return $val;
return '"' . str_replace(array("\\", "/", "\n", "\t", "\r", "\x08", "\x0c", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'), $val) . '"';
}
}
Index: branches/5.3.x/core/admin_templates/categories/edit_content.tpl
===================================================================
--- branches/5.3.x/core/admin_templates/categories/edit_content.tpl (revision 15945)
+++ branches/5.3.x/core/admin_templates/categories/edit_content.tpl (revision 15946)
@@ -1,108 +1,107 @@
<inp2:adm_SetPopupSize width="950" height="600"/>
<inp2:m_include t="incs/header"/>
-<inp2:m_NoDebug/>
<inp2:m_RenderElement name="combined_header" prefix="c" section="in-portal:browse" title_preset="edit_content"/>
<!-- ToolBar -->
<table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td>
<script type="text/javascript">
a_toolbar = new ToolBar();
a_toolbar.AddButton(
new ToolBarButton(
'select',
'<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>',
function() {
submit_event('content', 'OnSaveContentBlock');
}
)
);
a_toolbar.AddButton(
new ToolBarButton(
'cancel',
'<inp2:m_phrase label="la_ToolTip_Close" escape="1"/>',
function() {
window_close();
}
)
);
a_toolbar.Render();
</script>
</td>
<inp2:m_RenderElement name="ml_selector" prefix="content"/>
</tr>
</tbody>
</table>
<inp2:content_SaveWarning name="grid_save_warning"/>
<inp2:content_ErrorWarning name="form_error_warning"/>
<inp2:content_FCKEditor field="Content" width="99%" height="100" format="no_default"/>
<input type="hidden" name="c_id" value="<inp2:m_Get name='c_id'/>"/>
<script type="text/javascript">
var $field_id = '<inp2:content_InputName name="Content" js_escape="1"/>',
$autosave_title = '<inp2:m_Phrase name="la_title_EditingContentAutosaved" no_editing="1" js_escape="1"/>';
CKEDITOR.on(
'instanceReady',
function( ev ) {
var $editor_instance = CKEDITOR.instances[ ev.editor.name ];
$editor_instance.resize( '100%', $(window).height() - $('#cke_' + jq($field_id)).offset().top );
}
);
ckeditors_apply_typekit();
$(document).ready(
function () {
$(window).resize(
function ($e) {
for (var $index in CKEDITOR.instances) {
CKEDITOR.instances[$index].resize( '100%', $(window).height() - $('#cke_' + jq($field_id)).offset().top );
}
}
);
}
);
<inp2:m_if check="m_GetConfig" name="EnablePageContentRevisionControl">
setInterval(
function () {
var $editor_instance = CKEDITOR.instances[ '<inp2:content_InputName field="Content"/>' ];
$('#' + jq('<inp2:content_InputName field="Content"/>')).val( $editor_instance.getData() );
submit_event_ajax(
'content', 'OnAutoSave', undefined,
function ($autosave_string) {
$('#blue_bar').html( $autosave_title.replace('%s', $autosave_string) );
}
);
}, <inp2:m_GetConst name="CONTENT_LASTAUTOSAVE_UPDATE_INTERVAL"/> * 1000
);
setInterval(
function () {
submit_event_ajax(
'content', 'OnGetAutoSaveTime', undefined,
function ($autosave_string) {
if ( $autosave_string ) {
$('#blue_bar').html( $autosave_title.replace('%s', $autosave_string) );
}
}
);
}, <inp2:m_GetConst name="CONTENT_LASTAUTOSAVE_REFRESH_INTERVAL"/> * 1000
);
</inp2:m_if>
</script>
<inp2:m_include t="incs/footer"/>
\ No newline at end of file
Index: branches/5.3.x/core/admin_templates/img/top_frame/icons/saving_indicator.gif
===================================================================
Binary files branches/5.3.x/core/admin_templates/img/top_frame/icons/saving_indicator.gif (nonexistent) and branches/5.3.x/core/admin_templates/img/top_frame/icons/saving_indicator.gif (revision 15946) differ
Index: branches/5.3.x/core/admin_templates/js/template_manager.js
===================================================================
--- branches/5.3.x/core/admin_templates/js/template_manager.js (revision 15945)
+++ branches/5.3.x/core/admin_templates/js/template_manager.js (revision 15946)
@@ -1,597 +1,633 @@
function TemplateManager ( $settings ) {
+ this.languagePrefix = '';
this.pageId = 0;
this.editUrl = '';
this.browseUrl = '';
this.saveLayoutUrl = '';
+ this.saveContentUrl = '';
this.editingMode = 0; // from {1 - browse, 2 - content, 3 - design}
this.pageInfo = {editors: [], revisions: {}}; // information about page in "Content Mode"
+ this.pageInfoUpdateTimer = null;
+
+ this.revisionStatusMap = {
+ 1: 'cms-revision-published',
+ 2: 'cms-revision-pending',
+ 0: 'cms-revision-declined'
+ };
this._blocks = {};
- this._blockOrder = Array ();
+ this._blockOrder = [];
this.inDrag = false; // don't process mouse over/out events while in drag mode
$.extend(this, $settings);
- var $template_manager = this;
+ var $me = this;
+
+ $(document).ready(function() {
+ $me.init();
+ });
+}
- $(document).ready(
- function() {
- $template_manager.searchBlocks();
+TemplateManager.prototype.init = function () {
+ this.searchBlocks();
- if (!$template_manager.editingMode) {
- return ;
- }
+ if ( !this.editingMode ) {
+ return;
+ }
- // show special toolbar when in any of 3 browse modes
- var $head_frame = getFrame('head');
- var $extra_toolbar = $head_frame.$('div.front-extra-toolbar').clone(); // clone to keep original untouched
-
- $('a', $extra_toolbar).each(
- function() {
- // cut from end, because IE7 adds base_href to beginning of href
- var $editing_mode = $(this).attr('href');
- $editing_mode = $editing_mode.substr($editing_mode.length - 1, 1);
-
- $(this).attr('href', $template_manager.browseUrl.replace('#EDITING_MODE#', $editing_mode));
-
- if ($editing_mode == $template_manager.editingMode) {
- $(this).parents('td:first').addClass('button-active').prevAll('td:first').addClass('button-active');
- }
- }
- );
-
- $head_frame.$('#extra_toolbar').html( $extra_toolbar.html() );
-
- var $hover_effect = [];
-
- if ($template_manager.editingMode > 1) {
- // all modes except for "Browse Mode"
-// $hover_effect.push('div.cms-section-properties-btn:first');
- }
+ // show special toolbar when in any of 3 browse modes
+ var $template_manager = this,
+ $head_frame = getFrame('head'),
+ $extra_toolbar = $head_frame.$('div.front-extra-toolbar').clone(); // clone to keep original untouched
- if ($template_manager.editingMode == 2) {
- // Content Mode
-// $hover_effect.push('div.cms-edit-btn');
-// $hover_effect.push('div.admin-edit-btn');
-
- // make all spans with phrases clickable
- $template_manager.setupEditTranslationButtons(document);
-
- // hide "Revision History" div on every body click (bubbled), but not a "toolbar button", that opens it
- $('body').click(
- function ($e) {
- var $target = $($e.target),
- $id = $target.attr('id');
-
- if ( $id && ($id == 'div_history' || $target.parent().attr('id') == 'div_history') ) {
- return ;
- }
-
- $('#cms-revision-dropdown:visible').hide();
- }
- );
- }
+ $('a', $extra_toolbar).each(function () {
+ // cut from end, because IE7 adds base_href to beginning of href
+ var $editing_mode = $(this).attr('href');
+ $editing_mode = $editing_mode.substr($editing_mode.length - 1, 1);
- if ($template_manager.editingMode == 3) {
- // Design Mode
-// $hover_effect.push('div.cms-save-layout-btn:first, div.cms-cancel-layout-btn:first');
-
- $template_manager.renumberMovableElements();
-
- $('div.movable-area').sortable(
- {
- placeholder: 'move-helper',
- handle: '.movable-header',
- items: 'div.movable-element',
- connectWith: ['div.movable-area'],
- tolerance: 'pointer',
- start: function(e, ui) {
- $template_manager.inDrag = true;
- ui.placeholder.height( ui.item.height() );
- },
- stop: function(e, ui) {
- $template_manager.inDrag = false;
-
- // mouseout doesn't happen while in drag, so compensate it here
- var $header = $('.movable-header', ui.item);
- $('div.block-edit-block-btn-container', $header).mouseout();
- },
- change: function(e, ui) {
- $('div.cms-layout-btn-container').show();
- }
- }
- );
- }
+ $(this).attr('href', $template_manager.browseUrl.replace('#EDITING_MODE#', $editing_mode));
+
+ if ( $editing_mode == $template_manager.editingMode ) {
+ $(this).parents('td:first').addClass('button-active').prevAll('td:first').addClass('button-active');
+ }
+ });
- // make requested elements fully visible on mouseover
- if ( $hover_effect.length ) {
- $($hover_effect.join(', '))
- .mouseover(
- function(e) {
- $(this).css('opacity', 1);
- }
- )
- .mouseout(
- function(e) {
- $(this).css('opacity', 0.5);
- }
- );
+ $head_frame.$('#extra_toolbar').html($extra_toolbar.html());
+
+ var $hover_effect = [];
+
+ if ( $template_manager.editingMode > 1 ) {
+ // all modes except for "Browse Mode"
+// $hover_effect.push('div.cms-section-properties-btn:first');
+ }
+
+ if ( $template_manager.editingMode == 2 ) {
+ // Content Mode
+// $hover_effect.push('div.cms-edit-btn');
+// $hover_effect.push('div.admin-edit-btn');
+
+ // make all spans with phrases clickable
+ $template_manager.setupEditTranslationButtons(document);
+
+ // hide "Revision History" div on every body click (bubbled), but not a "toolbar button", that opens it
+ $('body').click(function ($e) {
+ var $target = $($e.target),
+ $id = $target.attr('id');
+
+ if ( $id && ($id == 'div_history' || $target.parent().attr('id') == 'div_history') ) {
+ return;
}
- // related to content revision control toolbar
- if ( $('#cms-revision-toolbar-layer').length == 1 ) {
- $template_manager.initRevisionToolbar();
+ $('#cms-revision-dropdown:visible').hide();
+ });
+ }
+
+ if ( $template_manager.editingMode == 3 ) {
+ // Design Mode
+// $hover_effect.push('div.cms-save-layout-btn:first, div.cms-cancel-layout-btn:first');
+
+ $template_manager.renumberMovableElements();
+
+ $('div.movable-area').sortable({
+ placeholder: 'move-helper',
+ handle: '.movable-header',
+ items: 'div.movable-element',
+ connectWith: ['div.movable-area'],
+ tolerance: 'pointer',
+ start: function (e, ui) {
+ $template_manager.inDrag = true;
+ ui.placeholder.height(ui.item.height());
+ },
+ stop: function (e, ui) {
+ $template_manager.inDrag = false;
+
+ // mouseout doesn't happen while in drag, so compensate it here
+ var $header = $('.movable-header', ui.item);
+ $('div.block-edit-block-btn-container', $header).mouseout();
+ },
+ change: function (e, ui) {
+ $('div.cms-layout-btn-container').show();
}
- }
- );
-}
+ });
+ }
+
+ // make requested elements fully visible on mouseover
+ if ( $hover_effect.length ) {
+ $($hover_effect.join(', '))
+ .mouseover(function (e) {
+ $(this).css('opacity', 1);
+ })
+ .mouseout(function (e) {
+ $(this).css('opacity', 0.5);
+ });
+ }
+
+ // related to content revision control toolbar
+ if ( $template_manager.revisionToolbarEnabled() ) {
+ $template_manager.initRevisionToolbar();
+ }
+
+ $('body')
+ .bind('InlineEditor.Focus', function ($e, $editor_event) {
+ $template_manager.inlineEditorFocus($editor_event);
+ })
+ .bind('InlineEditor.Blur', function ($e, $editor_event) {
+ $template_manager.inlineEditorBlur($editor_event);
+ });
+};
+
+TemplateManager.prototype.revisionToolbarEnabled = function () {
+ return $('#cms-revision-toolbar-layer').length == 1;
+};
TemplateManager.prototype.initRevisionToolbar = function () {
var $template_manager = this;
$('#cms-toggle-revision-toolbar').click(function ($e) {
var $me = $(this);
if ( $me.hasClass('opened') ) {
var $height = $('#cms-revision-toolbar').height();
$('#cms-revision-toolbar-layer').animate({top: (-1) * $height}, 'fast');
$('#cms-editing-notice, #cms-revision-dropdown').hide();
setCookie('toolbar_hidden', 1);
}
else {
$('#cms-revision-toolbar-layer').animate({top: 0}, 'fast');
setCookie('toolbar_hidden', 0);
}
$me.toggleClass('opened');
$e.preventDefault();
});
$('#cms-close-toolbar').click(function ($e) {
var $height = $('#cms-revision-toolbar').height();
$('#cms-toggle-revision-toolbar').removeClass('opened');
$('#cms-revision-toolbar-layer').css('top', (-1) * $height);
$('#cms-editing-notice, #cms-revision-dropdown').hide();
setCookie('toolbar_hidden', 1);
$e.preventDefault();
});
$('#cms-close-editing-notice').click(function ($e) {
$('#cms-editing-notice').hide();
$e.preventDefault();
});
- $('.toolbar-button', '#cms-revision-toolbar').click(function ($e) {
- var $button_name = $(this).attr('id').replace(/^(tool|div)_/, '');
+ $('body').on('click', '#cms-revision-dropdown .top .item', function ($e) {
+ $('a:first', this).click();
- $template_manager.revisionToolbarClick($button_name);
+ $e.preventDefault();
});
- setInterval(
- function () {
- $.getJSON(
- $('#kf_revisions_' + $template_manager.pageId).attr('action') + '&events[page-revision]=OnGetInfo',
- function ($data) {
- $template_manager.pageInfo = $data;
- $template_manager.processPageInfo();
- }
- );
- }, 20 * 1000 // 20 seconds
- );
+ $template_manager.requirePageInfoUpdate();
if ( !$.isEmptyObject($template_manager.pageInfo) ) {
$template_manager.processPageInfo();
}
-}
+};
-TemplateManager.prototype.processPageInfo = function () {
- var $class_mapping = {
- 1: 'cms-revision-published',
- 2: 'cms-revision-pending',
- 0: 'cms-revision-declined'
- };
+TemplateManager.prototype.requirePageInfoUpdate = function ($now) {
+ var $me = this;
- var $title = $('.revision-title', '#cms-current-revision-info');
+ if ( $now === undefined || $now === false ) {
+ clearTimeout(this.pageInfoUpdateTimer);
+ this.pageInfoUpdateTimer = setInterval(function () { $me.requirePageInfoUpdate(true); }, 20 * 1000); // 20 seconds
+
+ return;
+ }
- $title.html( this.pageInfo.current_revision.title );
- $('.draft-saved', '#cms-current-revision-info').html( this.pageInfo.current_revision.saved );
+ $.getJSON(
+ $('#kf_revisions_' + this.pageId).attr('action') + '&events[page-revision]=OnGetInfo',
+ function ($data) {
+ $me.pageInfo = $data;
+ $me.processPageInfo();
+ }
+ );
+};
- for (var $status in $class_mapping) {
- $title.toggleClass( $class_mapping[$status], $status === this.pageInfo.current_revision.status );
- }
+TemplateManager.prototype.processPageInfo = function () {
+ this.updateCurrentRevision();
if ( $('#cms-toggle-revision-toolbar').hasClass('opened') ) {
- var $notice = $('#cms-editing-notice');
+ this.showEditingNotice();
+ }
+
+ this.updateRevisionHistory();
+};
+
+TemplateManager.prototype.updateCurrentRevision = function () {
+ var $me = this,
+ $title = $('.revision-title', '#cms-current-revision-info');
- if ( this.pageInfo.editors.length ) {
- if ( $('span:first', $notice).attr('prev_editors') != this.pageInfo.editors.join(',') ) {
- // show notice, only when editors change occurs
- $('span:first', $notice).html(this.pageInfo.editors_warning).attr('prev_editors', this.pageInfo.editors.join(','));
-
- if ( $notice.is(':hidden') ) {
- $notice.fadeIn();
- }
+ $title.html(this.pageInfo.current_revision.title);
+ $('.draft-saved', '#cms-current-revision-info').html(this.pageInfo.current_revision.saved);
+
+ $.each(this.revisionStatusMap, function ($status, $class_name) {
+ $title.toggleClass($class_name, $status === $me.pageInfo.current_revision.status);
+ });
+
+ $.each(this.pageInfo.current_revision.toolbar_state, function ($button_name, $is_enabled) {
+ a_toolbar.SetEnabled($button_name, $is_enabled);
+ });
+};
+
+TemplateManager.prototype.showEditingNotice = function () {
+ var $notice = $('#cms-editing-notice');
+
+ if ( this.pageInfo.editors.length ) {
+ var $notice_span = $('span:first', $notice);
+
+ if ( $notice_span.data('prev_editors') != this.pageInfo.editors.join(',') ) {
+ // show notice, only when editors change occurs
+ $notice_span.html(this.pageInfo.editors_warning).data('prev_editors', this.pageInfo.editors.join(','));
+
+ if ( $notice.is(':hidden') ) {
+ $notice.fadeIn();
}
}
- else if ( $notice.is(':visible') ) {
- $notice.fadeOut();
- }
}
+ else if ( $notice.is(':visible') ) {
+ $notice.fadeOut();
+ }
+};
- var $revision_container = $('.top', '#cms-revision-dropdown'),
+TemplateManager.prototype.updateRevisionHistory = function () {
+ var $me = this,
+ $revision_container = $('.top', '#cms-revision-dropdown'),
$revision_mask = ' <div class="item">\
<span class="{CLASS}"><a href="{LINK}">{TITLE}</a> ({STATUS_LABEL})</span>\
<div class="cms-left">{DATETIME}</div>\
<div class="cms-right">{AUTHOR}</div>\
<div class="cms-clear"></div>\
</div>';
$revision_container.empty();
if ( $.isArray(this.pageInfo.revisions) ) {
- // no revisions yet
+ return;
}
- else {
- for (var $revision in this.pageInfo.revisions) {
- var $html = $revision_mask,
- $revision_info = this.pageInfo.revisions[$revision];
- for (var $field in $revision_info) {
- $html = $html.replace( new RegExp('{' + $field.toUpperCase() + '}', 'g'), $revision_info[$field] );
- }
+ $.each(this.pageInfo.revisions, function ($revision_number, $revision_info) {
+ var $html = $revision_mask;
- $html = $html.replace(/{CLASS}/g, $class_mapping[$revision_info.status] );
+ $.each($revision_info, function ($field, $value) {
+ $html = $html.replace(new RegExp('{' + $field.toUpperCase() + '}', 'g'), $value);
+ });
- if ( $revision_info['draft'] ) {
- $html = $html.replace(/{LINK}/g, this.browseUrl.replace('#EDITING_MODE#', 2) );
- }
- else {
- $html = $html.replace(/{LINK}/g, this.browseUrl.replace('#EDITING_MODE#', 2) + '&revision=' + $revision.substr(1) );
- }
+ $html = $html.replace(/{CLASS}/g, $me.revisionStatusMap[$revision_info.status]);
- $revision_container.append($html);
+ if ( $revision_info['draft'] ) {
+ $html = $html.replace(/{LINK}/g, $me.browseUrl.replace('#EDITING_MODE#', '2'));
+ }
+ else {
+ $html = $html.replace(/{LINK}/g, $me.browseUrl.replace('#EDITING_MODE#', '2') + '&revision=' + $revision_number.substr(1));
}
- $('.item', '#cms-revision-dropdown .top').each(
- function () {
- var $row = $(this);
-
- $('a:first', $row).click(
- function ($e) {
- $e.stopPropagation();
- }
- );
-
- $row.click(
- function ($e) {
- window.location.href = $('a:first', this).attr('href');
- }
- );
- }
- );
+ $revision_container.append($html);
+ });
+};
+
+TemplateManager.prototype.inlineEditorFocus = function ($editor_event) {
+ var $container = $($editor_event.editor.element.$).parent('.cms-edit-btn-container');
+
+ $container.removeClass('mode-inline-edit');
+};
+
+TemplateManager.prototype.inlineEditorBlur = function ($editor_event) {
+ var $me = this,
+ $element = $($editor_event.editor.element.$),
+ $container = $element.parent('.cms-edit-btn-container'),
+ $url_params = {},
+ $content_id = $container.data('content-id');
+
+ if ( $element.data('no_save_on_blur') === true ) {
+ $element.data('no_save_on_blur', null);
+ return;
}
-}
+
+ $element.css('position', 'static');
+ $container.addClass('mode-inline-saving');
+
+ $url_params["content[" + $content_id + "][" + this.languagePrefix + "Content]"] = $editor_event.editor.getData();
+
+ $.post(
+ this.saveContentUrl,
+ $url_params,
+ function ($data) {
+ if ( $data != 'OK' ) {
+ return;
+ }
+
+ if ( $me.revisionToolbarEnabled() ) {
+ $me.requirePageInfoUpdate(true);
+ }
+
+ $element.css('position', 'relative');
+ $container.removeClass('mode-inline-saving').addClass('mode-inline-edit');
+ }
+ );
+};
TemplateManager.prototype.revisionToolbarClick = function ($button_name) {
// console.log('button ', $button_name, ' clicked');
var $button_event_map = {
'select': 'OnSave',
'delete': 'OnDiscard',
'approve': 'OnPublish',
'decline': 'OnDecline'
};
if ( $button_event_map[$button_name] !== undefined ) {
$form_name = 'kf_revisions_' + this.pageId;
submit_event('page-revision', $button_event_map[$button_name]);
- return ;
+ return;
}
switch ( $button_name ) {
case 'preview':
var $url = this.browseUrl.replace('#EDITING_MODE#', 0).replace(/&(admin|editing_mode)=[\d]/g, '');
- window.open( $url + '&preview=1' );
+ window.open($url + '&preview=1');
break;
case 'history':
$('#cms-revision-dropdown').toggle();
break;
}
-}
+};
TemplateManager.prototype.setupEditTranslationButtons = function ($container) {
- $("span[name='cms-translate-phrase']", $container).each(
- function() {
- var $me = $(this);
- var $parent_link = $me.parents('a:first');
-
- if ($parent_link.length == 0) {
- // span in not inside "a" tag
-
- $me.prepend('<div class="cms-edit-btn"><div class="cms-btn-text">Edit</div></div>');
- $('div.cms-edit-btn:first', $me).click(TemplateManager.prototype.translatePhrase);
- $me.dblclick(
- function ($e) {
- $('div.cms-edit-btn:first', this).click();
-
- $e.preventDefault();
- }
- );
+ $("span[name='cms-translate-phrase']", $container).each(function() {
+ var $me = $(this),
+ $parent_link = $me.parents('a:first');
+
+ if ( $parent_link.length == 0 ) {
+ // span in not inside "a" tag
+ $me.prepend('<div class="cms-edit-btn"><div class="cms-btn-text">Edit</div></div>');
+ $('div.cms-edit-btn:first', $me).click(TemplateManager.prototype.translatePhrase);
- var $effect_element = $me;
- }
- else {
- // span is inside "a" tag
- var $clone = $me.clone();
- $clone.empty().attr('title', '');
-
- // in case if "a" tag is "display: block", then make "span" the same
- $clone.css('display', $parent_link.css('display'));
-
- $parent_link.html( $me.html() ).wrap($clone);
- $parent_link.before('<div class="cms-edit-btn" title="' + $me.attr('title') + '"><div class="cms-btn-text">Edit</div></div>');
- $parent_link.prev('div.cms-edit-btn:first').click(TemplateManager.prototype.translatePhrase);
+ $me.dblclick(function ($e) {
+ $('div.cms-edit-btn:first', this).click();
- var $effect_element = $parent_link.parents("span[name='cms-translate-phrase']:first");
- }
+ $e.preventDefault();
+ });
- $effect_element
- .mouseover(
- function($e) {
- $('div.cms-edit-btn', this).css('display', 'inline');
- }
- )
- .mouseout(
- function($e) {
- $('div.cms-edit-btn', this).hide();
- }
- );
+ var $effect_element = $me;
}
- );
-}
+ else {
+ // span is inside "a" tag
+ var $clone = $me.clone();
+ $clone.empty().attr('title', '');
+
+ // in case if "a" tag is "display: block", then make "span" the same
+ $clone.css('display', $parent_link.css('display'));
+
+ $parent_link.html($me.html()).wrap($clone);
+ $parent_link.before('<div class="cms-edit-btn" title="' + $me.attr('title') + '"><div class="cms-btn-text">Edit</div></div>');
+ $parent_link.prev('div.cms-edit-btn:first').click(TemplateManager.prototype.translatePhrase);
+
+ var $effect_element = $parent_link.parents("span[name='cms-translate-phrase']:first");
+ }
+
+ $effect_element
+ .mouseover(function($e) {
+ $('div.cms-edit-btn', this).css('display', 'inline');
+ })
+ .mouseout(function($e) {
+ $('div.cms-edit-btn', this).hide();
+ });
+ });
+};
TemplateManager.prototype.translatePhrase = function ($e) {
var $translate_url = $(this).parents("span[name='cms-translate-phrase']:first").attr('href');
- if ($translate_url.match(/javascript:(.*)/)) {
+ if ( $translate_url.match(/javascript:(.*)/) ) {
eval(RegExp.$1);
}
else {
window.location.href = $translate_url;
}
$e.preventDefault();
-}
+};
TemplateManager.prototype.renumberMovableElements = function () {
var $area_index = 0;
+
// 1. dynamically assign IDs to all movable elements
- $('div.movable-area').each(
- function() {
- var $element_index = 0;
- $('div.movable-element', this).each(
- function() {
- $(this).attr('id', 'target_order_a' + $area_index + 'e' + $element_index);
- $element_index++;
- }
- );
+ $('div.movable-area').each(function () {
+ var $element_index = 0;
- $area_index++;
- }
- );
-}
+ $('div.movable-element', this).each(function () {
+ $(this).attr('id', 'target_order_a' + $area_index + 'e' + $element_index);
+ $element_index++;
+ });
+
+ $area_index++;
+ });
+};
TemplateManager.prototype.saveLayout = function () {
// prepare order string
var $sort_order = [];
- $('div.movable-area').each(
- function($area_index) {
- var $order = $(this).sortable('serialize').replace(/target_order\[\]/g, 'target_order[' + $area_index + '][]');
- if ($order) {
- $sort_order.push($order);
- }
+
+ $('div.movable-area').each(function ($area_index) {
+ var $order = $(this).sortable('serialize').replace(/target_order\[\]/g, 'target_order[' + $area_index + '][]');
+
+ if ( $order ) {
+ $sort_order.push($order);
}
- );
+ });
+
$sort_order = $sort_order.join('&');
// save order string
var $me = this;
var $settings = {
url: this.saveLayoutUrl + '&' + $sort_order + '&width=200&height=70&modal=true',
caption: 'Layout Saving Result',
onDataReceived: function ($data) {
var $message = '';
- if ($data == 'OK') {
+ if ( $data == 'OK' ) {
$message = 'New Layout Saved';
$('div.cms-layout-btn-container').hide();
$me.renumberMovableElements();
}
else {
$message = 'Failed to Save New Layout';
}
$data = '<div style="text-align: center;">' + $message + '<br/><br/><input type="button" class="button" value="OK" onclick="TB.remove();"/></div>';
return $data;
}
};
- TB.setWindowTitle( window.top.document.title.replace(main_title + ' :: ', '') );
+ TB.setWindowTitle(window.top.document.title.replace(main_title + ' :: ', ''));
TB.show($settings);
-}
+};
TemplateManager.prototype.cancelLayout = function () {
window.location.href = window.location.href;
-}
+};
TemplateManager.prototype.onBtnClick = function ($e, $element) {
var $id = $element.id.replace(/_btn$/, '');
var $block_info = this._blocks[$id];
var $url = this.editUrl.replace('#BLOCK#', $block_info.block_name + ':' + $block_info.function_name).replace('#EVENT#', 'OnLoadBlock');
direct_edit('theme-file', $url);
$e.stopPropagation();
-}
+};
TemplateManager.prototype.onMouseOver = function ($e, $element) {
- if (this.inDrag) {
- return ;
+ if ( this.inDrag ) {
+ return;
}
$element = $($element);
- if ($element.hasClass('block-edit-design-btn-container')) {
+ if ( $element.hasClass('block-edit-design-btn-container') ) {
$($element).addClass('block-edit-design-btn-container-over');
var $button_group = $('div.cms-edit-design-btn-container:first', $element);
- if ($button_group.length) {
+
+ if ( $button_group.length ) {
$button_group.show();
}
else {
$('.cms-edit-design-btn:first', $element).show();
}
}
else {
$($element).addClass('block-edit-block-btn-container-over');
$('.cms-edit-block-btn:first', $element).show();
}
$e.stopPropagation();
-}
+};
TemplateManager.prototype.onMouseOut = function ($e, $element) {
- if (this.inDrag) {
- return ;
+ if ( this.inDrag ) {
+ return;
}
$element = $($element);
- if ($element.hasClass('block-edit-design-btn-container')) {
+ if ( $element.hasClass('block-edit-design-btn-container') ) {
$($element).removeClass('block-edit-design-btn-container-over');
var $button_group = $('div.cms-edit-design-btn-container:first', $element);
- if ($button_group.length) {
+
+ if ( $button_group.length ) {
$button_group.hide();
}
else {
$('.cms-edit-design-btn:first', $element).hide();
}
}
else {
$($element).removeClass('block-edit-block-btn-container-over');
$('.cms-edit-block-btn:first', $element).hide();
}
$e.stopPropagation();
-}
+};
TemplateManager.prototype.searchBlocks = function () {
var $design_containers = $('div.block-edit-design-btn-container');
var $block_containers = $('div.block-edit-block-btn-container');
- $design_containers.each(
- function() {
- var $block_container = $('div.block-edit-block-btn-container:first', this);
+ $design_containers.each(function () {
+ var $block_container = $('div.block-edit-block-btn-container:first', this);
- if ($block_container.length) {
- $block_containers = $block_containers.not($block_container);
+ if ( $block_container.length ) {
+ $block_containers = $block_containers.not($block_container);
- // place "Edit Block" button near "Edit Design" button
- var $edit_design_btn = $('.cms-edit-design-btn:first', this);
- var $edit_block_btn = $('.cms-edit-block-btn:first', $block_container);
+ // place "Edit Block" button near "Edit Design" button
+ var $edit_design_btn = $('.cms-edit-design-btn:first', this);
+ var $edit_block_btn = $('.cms-edit-block-btn:first', $block_container);
- $edit_design_btn
- .wrap('<div class="cms-edit-design-btn-container"></div>')
- .before( $edit_block_btn.clone() );
+ $edit_design_btn
+ .wrap('<div class="cms-edit-design-btn-container"></div>')
+ .before($edit_block_btn.clone());
- $edit_block_btn.remove();
+ $edit_block_btn.remove();
- // make "hint" from "Edit Block" button container main
- $(this).attr('title', $block_container.attr('title'));
- $block_container.attr('title', '');
+ // make "hint" from "Edit Block" button container main
+ $(this).attr('title', $block_container.attr('title'));
+ $block_container.attr('title', '');
- TemplateManager.prototype.registerBlock.call(aTemplateManager, $block_container.get(0), ['hover']);
- }
-
- TemplateManager.prototype.registerBlock.call(aTemplateManager, this, ['dblclick']);
+ TemplateManager.prototype.registerBlock.call(aTemplateManager, $block_container.get(0), ['hover']);
}
- );
- $block_containers.each(
- function() {
- TemplateManager.prototype.registerBlock.call(aTemplateManager, this);
- }
- );
+ TemplateManager.prototype.registerBlock.call(aTemplateManager, this, ['dblclick']);
+ });
-// $('div').each (
-// function () {
-// /*var $id = $(this).attr('id');
-//
-// if (!$id || $id.match(/parser_block\[.*\].*_btn$/) || !$id.match(/parser_block\[.*\]/)) {
-// // skip other divs
-// return true;
-// }*/
-//
-//
-// TemplateManager.prototype.registerBlock.call(aTemplateManager, this);
-// }
-// );
-}
+ $block_containers.each(function() {
+ TemplateManager.prototype.registerBlock.call(aTemplateManager, this);
+ });
+
+ /*$('div').each (function () {
+ *//*var $id = $(this).attr('id');
+
+ if ( !$id || $id.match(/parser_block\[.*\].*_btn$/) || !$id.match(/parser_block\[.*\]/) ) {
+ // skip other divs
+ return true;
+ }*//*
+
+
+ TemplateManager.prototype.registerBlock.call(aTemplateManager, this);
+ });*/
+};
TemplateManager.prototype.registerBlock = function ($element, $skip_events) {
var $params = $element.getAttribute('params').split(':');
this._blocks[$element.id] = {
block_name: $params[0],
function_name: $params[1]
};
var $btn = document.getElementById($element.id + '_btn');
- $($btn).click(
- function(ev) {
- TemplateManager.prototype.onBtnClick.call(aTemplateManager, ev, this);
- }
- );
+ $($btn).click(function (ev) {
+ TemplateManager.prototype.onBtnClick.call(aTemplateManager, ev, this);
+ });
- if ($skip_events === undefined) {
+ if ( $skip_events === undefined ) {
$skip_events = [];
}
- if (!in_array('dblclick', $skip_events)) {
- $($element)
- .dblclick(
- function(ev) {
- TemplateManager.prototype.onBtnClick.call(aTemplateManager, ev, this);
- }
- )
+ if ( !in_array('dblclick', $skip_events) ) {
+ $($element).dblclick(function (ev) {
+ TemplateManager.prototype.onBtnClick.call(aTemplateManager, ev, this);
+ });
}
- if (!in_array('hover', $skip_events)) {
+ if ( !in_array('hover', $skip_events) ) {
$($element)
- .mouseover(
- function(ev) {
- TemplateManager.prototype.onMouseOver.call(aTemplateManager, ev, this);
- }
- )
- .mouseout(
- function(ev) {
- TemplateManager.prototype.onMouseOut.call(aTemplateManager, ev, this);
- }
- );
+ .mouseover(function (ev) {
+ TemplateManager.prototype.onMouseOver.call(aTemplateManager, ev, this);
+ })
+ .mouseout(function (ev) {
+ TemplateManager.prototype.onMouseOut.call(aTemplateManager, ev, this);
+ });
}
this._blockOrder.push($element.id);
-}
\ No newline at end of file
+};
\ No newline at end of file
Index: branches/5.3.x/core/admin_templates/js/inp_ckconfig.js
===================================================================
--- branches/5.3.x/core/admin_templates/js/inp_ckconfig.js (revision 15945)
+++ branches/5.3.x/core/admin_templates/js/inp_ckconfig.js (revision 15946)
@@ -1,120 +1,131 @@
+CKEDITOR.config.title = '';
+
/*
* Append here extra CSS rules that should be applied into the editing area.
* Example:
* config.extraCss = "body {color:#FF0000;}";
*/
CKEDITOR.config.extraCss = "";
/**
* CKEditor's editing area body ID & class.
* This setting can be used if CKEditor does not work well with your theme by default.
*/
CKEDITOR.config.bodyClass = '';
CKEDITOR.config.bodyId = '';
// Preview
//CKEDITOR.config.PreviewUrl = '';
//CKEDITOR.config.ContentId = '';
//CKEDITOR.config.PreloadImages = [ CKEDITOR.config.SkinPath + 'images/toolbar.start.gif', CKEDITOR.config.SkinPath + 'images/toolbar.buttonarrow.gif', CKEDITOR.config.BasePath + 'plugins/images/document.gif' ] ;
//CKEDITOR.config.PluginsPath = CKEDITOR.config.BasePath + 'plugins/' ;
CKEDITOR.config.entities = false;
-CKEDITOR.config.extraPlugins = 'my_link,my_document,my_maximize';
+CKEDITOR.config.extraPlugins = 'my_link,my_document,my_maximize,my_inline';
//CKEDITOR.plugins.add('MySource');
//CKEDITOR.plugins.add('MyPreview');
//CKEDITOR.plugins.add('MyLink');
//CKEDITOR.plugins.add('MyImage');
//CKEDITOR.plugins.add('document', 'en,ru');
CKEDITOR.config.protectedSource.push( /(<inp2:[^\>]+>)|(<\/inp2:[^\>]+>)|(<inp2:[^\>]+\/>)/gi ) ;
CKEDITOR.config.documentIconsUrl = '/system/user_files/icons'; // for document custom plugin
CKEDITOR.config.toolbar_Default = [
['Cut','Copy','Paste','PasteText','PasteFromWord','-','NewPage','SelectAll','-','Find','Replace','-','Print','Preview','-',/*My*/ 'Link','Unlink','Anchor','HorizontalRule','-',/*My*/ 'Image','Flash','MediaEmbed','Document','Table','SpecialChar'],
'/',
['Bold','Italic','Underline','Strike','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','NumberedList','BulletedList','Outdent','Indent','-','Subscript','Superscript','-','TextColor','BGColor','-','Undo','Redo'],
'/',
['Styles','Font','FontSize','RemoveFormat','-','Scayt','-', /*My*/'Source', 'Maximize', 'ShowBlocks']
];
CKEDITOR.config.toolbar_DebugMode = [
['Cut','Copy','Paste','PasteText','PasteFromWord','-','NewPage','SelectAll','-','Find','Replace','-','Print','Preview','-',/*My*/ 'Link','Unlink','Anchor','HorizontalRule','-',/*My*/ 'Image','Flash','MediaEmbed','Document','Table','SpecialChar'],
'/',
['Bold','Italic','Underline','Strike','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','NumberedList','BulletedList','Outdent','Indent','-','Subscript','Superscript','-','TextColor','BGColor','-','Undo','Redo'],
'/',
['Styles','Font','FontSize','RemoveFormat','-','Scayt','-', /*My*/'Source', 'Maximize', 'ShowBlocks']
];
+CKEDITOR.config.toolbar_Inline = [
+ ['InlineSave', 'InlineCancel'],
+ ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Image', 'Document', 'MediaEmbed', 'Link', '-', 'Undo', 'Redo'],
+ ['Find', 'Replace', 'Scayt'],
+ '/',
+ ['Styles'], ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
+ ['NumberedList', 'BulletedList', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock']
+];
+
/*CKEDITOR.config.toolbar_Simple = [
['Styles'],
['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
['NumberedList', 'BulletedList', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo'],
['Find', 'Replace', 'Scayt']
];*/
//CKEDITOR.config.toolbar_Full = [
// [ 'Source','-','Save','NewPage','DocProps','Preview','Print','-','Templates' ],
// [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ],
// [ 'Find','Replace','-','SelectAll','-','SpellChecker', 'Scayt' ],
// [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ],
// '/',
// [ 'Bold','Italic','Underline','Strike','Subscript','Superscript','-','RemoveFormat' ],
// [ 'NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote','CreateDiv','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','BidiLtr','BidiRtl' ],
// [ 'Link','Unlink','Anchor' ],
// [ 'Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak' ],
// '/',
// [ 'Styles','Format','Font','FontSize' ],
// [ 'TextColor','BGColor' ],
// [ 'Maximize', 'ShowBlocks','-','About' ]
//];
CKEDITOR.config.enterMode = CKEDITOR.ENTER_BR ; // p | div | br
CKEDITOR.config.shiftEnterMode = CKEDITOR.ENTER_P ; // p | div | br
/*CKEDITOR.config.keystrokes = [
[ CKEDITOR.CTRL + 65 *//*A*//*, true ],
[ CKEDITOR.CTRL + 67 *//*C*//*, true ],
[ CKEDITOR.CTRL + 70 *//*F*//*, true ],
[ CKEDITOR.CTRL + 83 *//*S*//*, true ],
[ CKEDITOR.CTRL + 84 *//*T*//*, true ],
[ CKEDITOR.CTRL + 88 *//*X*//*, true ],
[ CKEDITOR.CTRL + 86 *//*V*//*, 'Paste' ],
[ CKEDITOR.CTRL + 45 *//*INS*//*, true ],
[ CKEDITOR.SHIFT + 45 *//*INS*//*, 'Paste' ],
[ CKEDITOR.CTRL + 88 *//*X*//*, 'Cut' ],
[ CKEDITOR.SHIFT + 46 *//*DEL*//*, 'Cut' ],
[ CKEDITOR.CTRL + 90 *//*Z*//*, 'Undo' ],
[ CKEDITOR.CTRL + 89 *//*Y*//*, 'Redo' ],
[ CKEDITOR.CTRL + CKEDITOR.SHIFT + 90 *//*Z*//*, 'Redo' ],
[ CKEDITOR.CTRL + 76 *//*L*//*, 'Link' ],
[ CKEDITOR.CTRL + 66 *//*B*//*, 'Bold' ],
[ CKEDITOR.CTRL + 73 *//*I*//*, 'Italic' ],
[ CKEDITOR.CTRL + 85 *//*U*//*, 'Underline' ],
[ CKEDITOR.CTRL + CKEDITOR.SHIFT + 83 *//*S*//*, 'Save' ],
[ CKEDITOR.CTRL + CKEDITOR.ALT + 13 *//*ENTER*//*, 'FitWindow' ]
] ;*/
//CKEDITOR.config.menu_groups = 'generic,anchor,flash,select,textarea,checkbox,radio,textfield,hiddenfield,imagebutton,button,bulletedlist,numberedlist,table,form';
CKEDITOR.config.font_names = 'Arial Narrow;Arial;Sans-Serif;Serif;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;
CKEDITOR.config.fontSize_sizes = 'xx-small;x-small;small;medium;large;x-large;xx-large' ;
CKEDITOR.config.filebrowserBrowseUrl = CKEDITOR.basePath + 'ckfinder/ckfinder.html';
CKEDITOR.config.filebrowserUploadUrl = CKEDITOR.basePath + 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files';
CKEDITOR.config.filebrowserImageBrowseUrl = CKEDITOR.basePath + 'ckfinder/ckfinder.html?type=Images';
CKEDITOR.config.filebrowserImageUploadUrl = CKEDITOR.basePath + 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images';
CKEDITOR.config.filebrowserFlashBrowseUrl = CKEDITOR.basePath + 'ckfinder/ckfinder.html?type=Flash';
CKEDITOR.config.filebrowserFlashUploadUrl = CKEDITOR.basePath + 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Flash';
CKEDITOR.config.filebrowserDocumentBrowseUrl = CKEDITOR.basePath + 'ckfinder/ckfinder.html?type=Documents';
// add ability to browse for documents
//CKEDITOR.config.documentsBrowser = true ;
Index: branches/5.3.x/core/admin_templates/incs/cms.css
===================================================================
--- branches/5.3.x/core/admin_templates/incs/cms.css (revision 15945)
+++ branches/5.3.x/core/admin_templates/incs/cms.css (revision 15946)
@@ -1,398 +1,424 @@
/* === Common styles for "Section Properties" and "Edit" buttons === */
div.cms-btn-image {
float: left;
height: 15px;
vertical-align: middle;
}
div.cms-btn-text {
margin-left: 3px;
float: left;
white-space: nowrap;
vertical-align: middle;
}
div.cms-btn-content {
padding: 5px;
+ min-height: 15px;
}
.cms-edit-btn {
padding: 2px 5px;
font-family: Arial, Verdana;
font-size: 13px;
font-weight: normal;
color: black;
cursor: pointer;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
.cms-section-properties-btn, .cms-edit-btn, .cms-edit-block-btn, .cms-edit-design-btn {
width: auto;
position: absolute;
z-index: 1000099;
}
.cms-edit-btn, .cms-edit-block-btn, .cms-edit-design-btn {
margin-top: -10px;
}
div.cms-edit-design-btn-container {
position: absolute;
margin-left: -10px;
margin-top: -10px;
display: none;
}
div.cms-edit-design-btn-container .cms-edit-block-btn, div.cms-edit-design-btn-container .cms-edit-design-btn {
float: left;
display: block;
position: relative;
margin: 0px;
}
div.cms-edit-design-btn-container .cms-edit-design-btn {
margin-left: 4px;
}
/* === Styles for "Section Properties" button === */
.cms-section-properties-btn {
float: right;
position: relative;
border-color: #A1D0A1;
background-color: #CCFF00;
}
div.cms-section-properties-btn-container {
border: 1px dashed #A1D0A1;
margin: 10px;
}
/* === Styles for "Edit" button === */
.cms-btn-new {
cursor: pointer;
background: url(@templates_base@/img/top_frame/icons/content_mode.png) #CCFF00 3px center no-repeat;
padding: 2px 2px 2px 17px;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border: 2px solid #A1D0A1;
opacity: 0.5;
filter: alpha(opacity=50);
color: black;
font-family: Arial, Verdana;
font-size: 13px;
font-weight: normal;
}
.cms-btn-new:hover {
opacity: 1;
filter: alpha(opacity=100);
}
div.cms-edit-btn-container {
+ position: relative;
border: 1px dashed #FF6E00;
}
+.cms-edit-btn-container[data-content-id] .cms-btn-content { padding: 0; min-height: 25px; }
+.cms-edit-btn-container .inline-edit-layer, .cms-edit-btn-container .inline-saving-layer { display: none; }
+
+.cms-edit-btn-container.mode-inline-edit .inline-edit-layer { display: block; }
+
+.cms-edit-btn-container .inline-edit-layer {
+ position: absolute;
+ background: url(@templates_base@/img/top_frame/icons/content_mode.png) center no-repeat;
+ width: 20px;
+ height: 20px;
+ top: 0px;
+ right: 0px;
+}
+
+.cms-edit-btn-container.mode-inline-saving .inline-saving-layer { display: block; }
+
+.cms-edit-btn-container .inline-saving-layer {
+ position: absolute;
+ background: url(@templates_base@/img/top_frame/icons/saving_indicator.gif) no-repeat 100% 0px rgba(255, 255, 255, .9);
+ width: 100%;
+ top: 0px;
+ bottom: 0px;
+}
+
div.cms-edit-btn {
border: 2px solid #FF6E00;
}
.cms-edit-btn {
margin-left: -10px;
border-color: #FF6E00;
background-color: #FFCC00;
}
.cms-edit-block-btn {
border-color: #FF6E00;
background-color: #FFCC00;
display: none;
}
.cms-edit-design-btn {
border-color: #A1D0A1;
background-color: #CCFF00;
display: none;
}
.admin-edit-btn {
border-color: #A1D0A1;
background-color: #CCFF00;
}
/* === Styles for "Save" and "Cancel" buttons (for layout) === */
div.cms-layout-btn-container {
position: absolute;
display: none;
z-index: 1000099;
}
.cms-save-layout-btn, .cms-cancel-layout-btn {
float: left;
width: auto;
}
.cms-save-layout-btn {
color: white;
border-color: #1C960C;
background-color: #24B30D;
}
.cms-cancel-layout-btn {
color: white;
border-color: #C81900;
background-color: #DE2A00;
}
.cms-cancel-layout-btn {
margin-left: 4px;
}
/* === Styles for Template Editor === */
div.block-edit-block-btn-container, div.block-edit-design-btn-container {
border: 1px dashed transparent;
}
div.block-edit-block-btn-container .cms-btn-new, div.block-edit-design-btn-container .cms-btn-new {
opacity: 1;
filter: alpha(opacity = 100);
}
div.block-edit-block-btn-container-over, div.block-edit-design-btn-container-over {
border-color: #FF6E00;
}
/*div.block-edit-design-btn-container-over {
border-color: #A1D0A1;
}*/
/* === Styles for element moving/sorting in theme === */
div.movable-area {
min-height: 200px;
}
.move-helper {
border: 3px dashed #666;
/*width: auto !important;*/
}
/* === Styles for phrase translation links === */
span[name='cms-translate-phrase'] {
text-decoration: none;
border: 1px dashed transparent;
padding: 3px;
}
span[name='cms-translate-phrase']:hover {
border-color: #FF6E00;
}
span[name='cms-translate-phrase'] .cms-btn-text {
font-size: 9px;
}
span[name='cms-translate-phrase'] .cms-edit-btn, span[name='cms-translate-phrase'] .admin-edit-btn {
display: none;
opacity: 1;
filter: alpha(opacity=100);
}
/* === Misc Styles for "Content Revision Control" button === */
.cms-clear { clear: both; }
.cms-right { float: right; }
.cms-left { float: left; }
/* === Current Revision Information === */
#cms-current-revision-info {
color: #4b4b4b;
font-size: 11px;
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
white-space: nowrap;
float: left;
padding: 0px 30px;
}
#cms-current-revision-info span {
display: block;
/*color: #008c1b;*/
font-size: 16px;
display: block;
padding: 10px 0px 3px 0px;
}
#cms-current-revision-info span.cms-revision-published { color: #15b300; }
#cms-current-revision-info span.cms-revision-pending { color: #ff9600; }
#cms-current-revision-info span.cms-revision-declined { color: #f90000; }
/* === Revision Editing Toolbar === */
#cms-revision-toolbar {
background-color: #F0F1EB;
border-collapse: collapse;
border-color: #aaaaaa;
border-style: solid;
border-width: 0 1px 1px;
font-size: 8pt;
}
#cms-revision-toolbar-layer {
position: fixed;
width: 630px;
top: 0px;
z-index: 1000100;
}
.toolbar-button, .toolbar-button-disabled, .toolbar-button-over {
float: left;
text-align: center;
font-size: 8pt;
padding: 5px;
vertical-align: middle;
color: #006F99;
}
.toolbar-button-over {
color: #000;
}
.toolbar-button-disabled {
color: #444;
}
a#cms-toggle-revision-toolbar {
display: block;
background: url(@templates_base@/img/top_frame/revision_control/button_vp_right.png) top right no-repeat;
padding-right: 24px;
float: right;
margin-top: -1px;
text-decoration: none;
}
a#cms-toggle-revision-toolbar span {
display: block;
background: url(@templates_base@/img/top_frame/revision_control/button_vp_left.png) top left no-repeat;
line-height: 30px;
color: #000000;
font-family: Arial, Helvetica, sans-serif;
font-size: 13px;
font-weight: bold;
padding: 0px 10px 0px 15px;
}
a#cms-toggle-revision-toolbar:hover span {
color: #666666;
}
a#cms-toggle-revision-toolbar.opened {
background: url(@templates_base@/img/top_frame/revision_control/button_vp_right2.png) top right no-repeat;
}
#cms-close-toolbar {
float: right;
display: block;
width: 10px;
height: 10px;
background: url(@templates_base@/img/top_frame/revision_control/close_black.gif) top left;
overflow: hidden;
margin: 10px 10px 0 0;
}
/* === Revision Editing Notice === */
#cms-editing-notice {
width: 230px;
position: fixed;
z-index: 1000101;
margin-top: 50px;
margin-left: 10px;
display: none;
}
#cms-editing-notice .top {
background: url(@templates_base@/img/top_frame/revision_control/message_background_red.png) left top no-repeat;
padding: 30px 20px 10px 20px;
color: #FFFFFF;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
}
#cms-editing-notice .bottom {
background: url(@templates_base@/img/top_frame/revision_control/message_background_red.png) left bottom no-repeat;
height: 6px;
}
#cms-close-editing-notice {
float:right;
display:block;
width:10px;
height:10px;
background:url(@templates_base@/img/top_frame/revision_control/close_white.gif) top left;
overflow:hidden;
margin:-5px -10px 0 0;
}
/* === Revision Dropdown === */
#cms-revision-dropdown {
width: 240px;
position: fixed;
margin-left: 260px;
margin-top: 30px;
z-index: 1000102;
display: none;
}
#cms-revision-dropdown .top {
border-top: 1px solid #aaaaaa;
border-left: 1px solid #aaaaaa;
border-right: 1px solid #aaaaaa;
}
#cms-revision-dropdown .item, #cms-revision-dropdown .item:hover {
color: #666666;
background: url(@templates_base@/img/top_frame/revision_control/history_item_background.gif) top left repeat-x #FFFFFF;
padding: 10px 13px;
border-top: 1px solid #e7e7e7;
font-size: 11px;
cursor: pointer;
}
#cms-revision-dropdown .item:hover {
background: url(@templates_base@/img/top_frame/revision_control/history_item_background_hover.gif) top left repeat-x #F8F8F8;
}
#cms-revision-dropdown .item .red {
color: #FF0000;
padding-top: 6px;
}
#cms-revision-dropdown .bottom {
background: url(@templates_base@/img/top_frame/revision_control/history_bottom.png) top left no-repeat;
height: 6px;
}
.item .cms-revision-published, .item .cms-revision-pending, .item .cms-revision-declined {
display: block;
font-size: 13px;
font-weight: bold;
padding-bottom: 8px;
}
.item .cms-revision-published, .item .cms-revision-published a { color: #15b300 !important; }
.item .cms-revision-published a:hover { color: #1ada00 !important; }
.item .cms-revision-pending, .item .cms-revision-pending a { color: #ff9600 !important; }
.item .cms-revision-pending a:hover { color: #ffba58 !important; }
.item .cms-revision-declined, .item .cms-revision-declined a { color: #f90000 !important; }
.item .cms-revision-declined a:hover { color: #ff6666 !important; }
\ No newline at end of file

Event Timeline