Index: trunk/core/kernel/constants.php =================================================================== diff -u -N -r8078 -r8413 --- trunk/core/kernel/constants.php (.../constants.php) (revision 8078) +++ trunk/core/kernel/constants.php (.../constants.php) (revision 8413) @@ -20,6 +20,7 @@ safeDefine('STATUS_DISABLED', 0); safeDefine('STATUS_ACTIVE', 1); safeDefine('STATUS_PENDING', 2); + safeDefine('STATUS_PENDING_EDITING', -2); // sections define('stTREE', 1); Index: trunk/kernel/admin_templates/incs/image_blocks.tpl =================================================================== diff -u -N -r8397 -r8413 --- trunk/kernel/admin_templates/incs/image_blocks.tpl (.../image_blocks.tpl) (revision 8397) +++ trunk/kernel/admin_templates/incs/image_blocks.tpl (.../image_blocks.tpl) (revision 8413) @@ -8,7 +8,7 @@
  - + -
@@ -51,7 +51,7 @@
 
+ Index: trunk/core/units/general/cat_event_handler.php =================================================================== diff -u -N -r8409 -r8413 --- trunk/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 8409) +++ trunk/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 8413) @@ -20,7 +20,7 @@ 'OnCancelAction' => Array('self' => true), ); - + $this->permMapping = array_merge($this->permMapping, $permissions); } @@ -46,7 +46,7 @@ $object->setID($id); } } - + /** * Checks permissions of user * @@ -89,7 +89,7 @@ if (strlen($selected_ids)) { $perm_helper =& $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ - + $items = $perm_helper->GetCategoryItemData($event->Prefix, $selected_ids); $check_method = ($event->Name == 'OnMassDelete') ? 'DeleteCheckPermission' : 'ModifyCheckPermission'; foreach ($items as $item_id => $item_data) { @@ -187,7 +187,7 @@ $type_clauses['my_items']['include'] = '%1$s.CreatedById = '.$user_id; $type_clauses['my_items']['except'] = '%1$s.CreatedById <> '.$user_id; $type_clauses['my_items']['having_filter'] = false; - + $type_clauses['pick']['include'] = '%1$s.EditorsPick = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1'; $type_clauses['pick']['except'] = '%1$s.EditorsPick! = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1'; $type_clauses['pick']['having_filter'] = false; @@ -375,26 +375,10 @@ $object->addFilter('perm_filter', 'perm.PermId = '.$view_perm); - if ( !$this->Application->IsAdmin() ) - { - $object->addFilter('status_filter', '%1$s.Status = 1'); - if ($this->Application->getUnitOption($event->Prefix, 'UsePendingEditing')) { - // if category item uses pending editing abilities, then in no cases show pending copies on front - $object->addFilter('original_filter', '%1$s.OrgId = 0 OR %1$s.OrgId IS NULL'); - } - } - else { - if ($this->Application->getUnitOption($event->Prefix, 'UsePendingEditing')) { - $pending_ids = $this->Conn->GetCol( - 'SELECT OrgId FROM '.$object->TableName.' - WHERE Status = -2 AND OrgId IS NOT NULL'); - if ($pending_ids) { - $object->addFilter('no_original_filter', '%1$s.'.$object->IDField.' NOT IN ('.implode(',', $pending_ids).')'); - } - } - } $types = $event->getEventParam('types'); + $this->applyItemStatusFilter($object, $types); + $except_types = $event->getEventParam('except'); $type_clauses = $this->getTypeClauses($event); @@ -482,6 +466,65 @@ } /** + * Adds filter that filters out items with non-required statuses + * + * @param kDBList $object + * @param string $types + */ + function applyItemStatusFilter(&$object, $types) + { + // Link1 (before modifications) [Status = 1, OrgId = NULL], Link2 (after modifications) [Status = -2, OrgId = Link1_ID] + $pending_editing = $this->Application->getUnitOption($object->Prefix, 'UsePendingEditing'); + + if ( !$this->Application->IsAdmin() ) { + $types = explode(',', $types); + if (in_array('my_items', $types)) { + $allow_statuses = Array (STATUS_ACTIVE, STATUS_PENDING, STATUS_PENDING_EDITING); + $object->addFilter('status_filter', '%1$s.Status IN ('.implode(',', $allow_statuses).')'); + + if ($pending_editing) { + $user_id = $this->Application->RecallVar('user_id'); + $this->applyPendingEditingFilter($object, $user_id); + } + } + else { + $object->addFilter('status_filter', '%1$s.Status = 1'); + if ($pending_editing) { + // if category item uses pending editing abilities, then in no cases show pending copies on front + $object->addFilter('original_filter', '%1$s.OrgId = 0 OR %1$s.OrgId IS NULL'); + } + } + } + else { + if ($pending_editing) { + $this->applyPendingEditingFilter($object); + } + } + } + + /** + * Adds filter, that removes live items if they have pending editing copies + * + * @param kDBList $object + * @param int $user_id + */ + function applyPendingEditingFilter(&$object, $user_id = null) + { + $sql = 'SELECT OrgId + FROM '.$object->TableName.' + WHERE Status = '.STATUS_PENDING_EDITING.' AND OrgId IS NOT NULL'; + + if (isset($user_id)) { + $sql .= ' AND CreatedById = '.$user_id; + } + + $pending_ids = $this->Conn->GetCol($sql); + if ($pending_ids) { + $object->addFilter('no_original_filter', '%1$s.'.$object->IDField.' NOT IN ('.implode(',', $pending_ids).')'); + } + } + + /** * Adds calculates fields for item statuses * * @param kCatDBItem $object @@ -1740,15 +1783,15 @@ if ($this->Application->IsAdmin()) { return true; } - + $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing'); if ($use_pending_editing) { $object =& $event->getObject(); /* @var $object kDBItem */ - + $perm_helper =& $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ - + $primary_category = $object->GetDBField('CategoryId') > 0 ? $object->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id'); $item_status = $perm_helper->AddCheckPermission($primary_category, $event->Prefix); if ($item_status == STATUS_DISABLED) { @@ -1760,7 +1803,7 @@ } } } - + /** * Creates category item & redirects to confirmation template (front-end only) * @@ -1771,7 +1814,7 @@ parent::OnCreate($event); $this->SetFrontRedirectTemplate($event, 'suggest'); } - + /** * Creates category item & redirects to confirmation template (front-end only) * @@ -1782,7 +1825,7 @@ parent::OnUpdate($event); $this->SetFrontRedirectTemplate($event, 'modify'); } - + /** * Sets next template to one required for front-end after adding/modifying item * @@ -1794,14 +1837,14 @@ if ($this->Application->IsAdmin() || $event->status != erSUCCESS) { return ; } - + $event->SetRedirectParam('opener', 's'); - + $object =& $event->getObject(); $next_template = $object->GetDBField('Status') == STATUS_ACTIVE ? 'confirm_template' : 'pending_confirm_template'; $event->redirect = $this->Application->GetVar($template_key.'_'.$next_template); } - + /** * Apply same processing to each item beeing selected in grid * @@ -1843,7 +1886,7 @@ } } } - + /** * Deletes items & preserves clean env * @@ -1852,13 +1895,13 @@ function OnMassDelete(&$event) { parent::OnMassDelete($event); - + if ($event->status == erSUCCESS && !$this->Application->IsAdmin()) { $event->SetRedirectParam('pass', 'm'); $event->SetRedirectParam('m_cat_id', 0); } } - + /** * Checks, that currently loaded item is allowed for viewing (non permission-based) * @@ -1871,14 +1914,14 @@ if (!$object->isLoaded()) { return true; } - + $status = $object->GetDBField('Status'); - + $user_id = $this->Application->RecallVar('user_id'); if (($status == -2 || $status == STATUS_PENDING) && ($object->GetDBField('CreatedById') == $user_id)) { return true; } - + return $status == STATUS_ACTIVE; } } Index: trunk/core/kernel/utility/debugger.php =================================================================== diff -u -N -r8402 -r8413 --- trunk/core/kernel/utility/debugger.php (.../debugger.php) (revision 8402) +++ trunk/core/kernel/utility/debugger.php (.../debugger.php) (revision 8413) @@ -325,7 +325,7 @@ if ($has_args) { // if parameter value is longer then 200 symbols, then leave only first 50 - $args = $this->highlightString($this->print_r($traceRec['args'], true, 50, 200)); + $args = $this->highlightString($this->print_r($traceRec['args'], true)); $ret .= ''; } $i++; @@ -409,26 +409,36 @@ * * @param Array $array * @param bool $return_output return output or print it out - * @param int $cut_first cut first N symbols, don't cut anything if -1 specified - * @package int $cut_min_length cut only of this length of string or greather + * @param int $tab_count offset in tabs * @return string */ - function print_r(&$array, $return_output = false, $cut_first = -1, $cut_min_length = -1) + function print_r(&$array, $return_output = false, $tab_count = -1) { - static $first_line = true, $tab_count = -1; + static $first_line = true; - if (is_null($array)) { - return 'NULL'; - } - elseif (!is_array($array)) { - if ($cut_min_length != -1 && strlen($array) > $cut_min_length) { - $array = substr($array, 0, $cut_first).' ...'; + // not an array at all + if (!is_array($array)) { + switch (gettype($array)) { + case 'NULL': + return 'NULL'."\n"; + break; + + case 'object': + return $this->processObject($array, $tab_count); + break; + + default: + // number or string + if (strlen($array) > 200) { + $array = substr($array, 0, 50).' ...'; + } + return $array."\n"; + break; } - return $array; } - + $output = ''; - + $tab_count++; $output .= "Array\n".str_repeat(' ', $tab_count)."(\n"; @@ -440,7 +450,7 @@ foreach ($array_keys as $key) { switch (gettype($array[$key])) { case 'array': - $output .= $tabsign.'['.$key.'] = '.$this->print_r($array[$key], true, 50, 200); + $output .= $tabsign.'['.$key.'] = '.$this->print_r($array[$key], true, $tab_count); break; case 'boolean': @@ -450,8 +460,8 @@ case 'integer': case 'double': case 'string': - if ($cut_min_length != -1 && strlen($array[$key]) > $cut_min_length) { - $array[$key] = substr($array[$key], 0, $cut_first).' ...'; + if (strlen($array[$key]) > 200) { + $array[$key] = substr($array[$key], 0, 50).' ...'; } $output .= $tabsign.'['.$key.'] = '.$array[$key]."\n"; break; @@ -461,42 +471,10 @@ break; case 'object': - $attribute_names = get_class_vars( get_class($array[$key]) ); - if (!$attribute_names) { - $output .= $tabsign.'['.$key."] = NO_ATTRIBUTES\n"; - } - else { - if ($this->IsBigObject($array[$key])) { - $output .= $tabsign.'['.$key.'] = SKIPPED (class: '.get_class($array[$key]).")\n"; - break; - } - - // $attribute_value - default value for this attribute, not used here - foreach ($attribute_names as $attribute_name => $attribute_value) { - if (is_object($array[$key]->$attribute_name)) { - // it is object - $object_class = get_class($array[$key]->$attribute_name); - if (!in_array($object_class, $this->RecursionStack)) { - // object [not in recursion stack] - if ($this->IsBigObject($array[$key]->$attribute_name)) { - $output .= $tabsign.'['.$attribute_name.'] = SKIPPED (class: '.$object_class.")\n"; - continue; - } - - array_push($this->RecursionStack, $object_class); - $output .= $this->print_r($array[$key]->$attribute_name, true, 50, 200); - array_pop($this->RecursionStack); - } - else { - // object [in recursion stack] - $output .= $tabsign.'['.$attribute_name.'] = *** RECURSION *** (class: '.$object_class.")\n"; - } - } - else { - $output .= $tabsign.'['.$attribute_name.'] = '.$this->print_r($array[$key]->$attribute_name, true, 50, 200)."\n"; - } - } - } + $output .= $tabsign.'['.$key."] = "; + $output .= "Object (".get_class($array[$key]).") = \n".str_repeat(' ', $tab_count + 1)."(\n"; + $output .= $this->processObject($array[$key], $tab_count + 2); + $output .= str_repeat(' ', $tab_count + 1).")\n"; break; default: @@ -506,7 +484,7 @@ } $tab_count--; - $output .= str_repeat(' ', $tab_count).")\n"; + $output .= str_repeat(' ', $tab_count).")\n"; if ($first_line) { $first_line = false; @@ -525,18 +503,40 @@ return true; } - /** - * Returns only first 200 chars of string, this allow to save amount of data sent to browser - * - * @param string $string - * @return string - */ - function cutStringForHTML($string) + function processObject(&$object, $tab_count) { - if (strlen($string) > 200) { - $string = substr($string,0,50).' ...'; + $object_class = get_class($object); + if (!in_array($object_class, $this->RecursionStack)) { + if ($this->IsBigObject($object)) { + return 'SKIPPED (class: '.$object_class.")\n"; + } + + $attribute_names = get_class_vars($object_class); + if (!$attribute_names) { + return "NO_ATTRIBUTES\n"; + } + else { + $output = ''; + array_push($this->RecursionStack, $object_class); + + $tabsign = $tab_count ? str_repeat(' ', $tab_count) : ''; + foreach ($attribute_names as $attribute_name => $attribute_value) { + if (is_object($object->$attribute_name)) { + // it is object + $output .= $tabsign.'['.$attribute_name.'] = '.$this->processObject($object->$attribute_name, $tab_count + 1); + } + else { + $output .= $tabsign.'['.$attribute_name.'] = '.$this->print_r($object->$attribute_name, true, $tab_count); + } + } + array_pop($this->RecursionStack); + return $output; + } } - return $string; + else { + // object [in recursion stack] + return '*** RECURSION *** (class: '.$object_class.")\n"; + } } /** Index: trunk/core/admin_templates/incs/image_blocks.tpl =================================================================== diff -u -N -r8397 -r8413 --- trunk/core/admin_templates/incs/image_blocks.tpl (.../image_blocks.tpl) (revision 8397) +++ trunk/core/admin_templates/incs/image_blocks.tpl (.../image_blocks.tpl) (revision 8413) @@ -8,7 +8,7 @@
  -
@@ -91,9 +91,9 @@ function FieldID($field_name) { var $field_mask = ''; - return $field_mask.replace('#FIELD#', $field_name); + return $field_mask.replace('#FIELD#', $field_name); } - + function toggle_fullsize() { if (document.getElementById('_cb_' + FieldID('SameImages')).checked) { document.getElementById(FieldID('LocalImage') + '_0').disabled = true; @@ -108,7 +108,7 @@ document.getElementById(FieldID('Url')).disabled = false; } } - + if (document.getElementById('_cb_' + FieldID('DefaultImg')).checked) { document.getElementById('_cb_' + FieldID('DefaultImg')).disabled = true; document.getElementById('_cb_' + FieldID('Enabled')).disabled = true; @@ -120,7 +120,7 @@ document.getElementById(FieldID('Enabled')).value = 1; } } - + function check_primary() { if (!document.getElementById('_cb_' + FieldID('Enabled')).checked) { document.getElementById('_cb_' + FieldID('DefaultImg')).checked = false; @@ -145,7 +145,7 @@ - + + -
@@ -51,7 +51,7 @@
 
+ Index: trunk/kernel/include/globals.php =================================================================== diff -u -N -r8104 -r8413 --- trunk/kernel/include/globals.php (.../globals.php) (revision 8104) +++ trunk/kernel/include/globals.php (.../globals.php) (revision 8413) @@ -82,6 +82,7 @@ if( !defined('STATUS_DISABLED') ) define('STATUS_DISABLED', 0); if( !defined('STATUS_ACTIVE') ) define('STATUS_ACTIVE', 1); if( !defined('STATUS_PENDING') ) define('STATUS_PENDING', 2); +if( !defined('STATUS_PENDING_EDITING') ) define('STATUS_PENDING_EDITING', -2); $LogLevel = 0; $LogFile = NULL; Index: trunk/core/units/users/users_event_handler.php =================================================================== diff -u -N -r8409 -r8413 --- trunk/core/units/users/users_event_handler.php (.../users_event_handler.php) (revision 8409) +++ trunk/core/units/users/users_event_handler.php (.../users_event_handler.php) (revision 8413) @@ -25,10 +25,10 @@ 'OnSubscribeUser' => Array('self' => true), 'OnRecommend' => Array('self' => true), - + 'OnItemBuild' => Array('self' => true), ); - + $this->permMapping = array_merge($this->permMapping, $permissions); } @@ -296,7 +296,7 @@ { $prefix_special = $this->Application->IsAdmin() ? 'u.current' : 'u'; // "u" used on front not to change theme $object =& $this->Application->recallObject($prefix_special, null, Array('skip_autoload' => true)); - + $next_template = $this->Application->GetVar('next_template'); if ($next_template == '_ses_redirect') { $location = $this->Application->BaseURL().$this->Application->RecallVar($next_template); @@ -1208,7 +1208,7 @@ } } - + /** * Checks, that currently loaded item is allowed for viewing (non permission-based) * @@ -1218,10 +1218,12 @@ function checkItemStatus(&$event) { $object =& $event->getObject(); - $status = $object->GetDBField('Status'); - + if (!$object->isLoaded()) { + return true; + } + $virtual_users = Array (-1, -2); // root, Guest - return ($status == STATUS_ACTIVE) || in_array($object->GetID(), $virtual_users); + return ($object->GetDBField('Status') == STATUS_ACTIVE) || in_array($object->GetID(), $virtual_users); } } Index: trunk/core/kernel/db/db_event_handler.php =================================================================== diff -u -N -r8408 -r8413 --- trunk/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 8408) +++ trunk/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 8413) @@ -96,9 +96,9 @@ $permissions = Array( 'OnLoad' => Array('self' => 'view', 'subitem' => 'view'), 'OnItemBuild' => Array('self' => 'view', 'subitem' => 'view'), - + 'OnBuild' => Array('self' => true), - + 'OnNew' => Array('self' => 'add', 'subitem' => 'add|edit'), 'OnCreate' => Array('self' => 'add', 'subitem' => 'add|edit'), 'OnUpdate' => Array('self' => 'edit', 'subitem' => 'add|edit'), @@ -375,15 +375,19 @@ if (!$status_fields) { return true; } - + $status_field = array_shift($status_fields); if ($status_field == 'Status' || $status_field == 'Enabled') { $object =& $event->getObject(); + if (!$object->isLoaded()) { + return true; + } + return $object->GetDBField($status_field) == STATUS_ACTIVE; } return true; } - + /** * Builds item (loads if needed) * @@ -405,19 +409,20 @@ if ($auto_load && !$skip_autload) { $perm_status = true; + $user_id = $this->Application->RecallVar('user_id'); $event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true)); - if ($this->Application->RecallVar('user_id') == -1 || $this->CheckPermission($event)) { + if ($user_id == -1 || $this->CheckPermission($event)) { // don't autoload item, when user doesn't have view permission $this->LoadItem($event); - - if (!$this->checkItemStatus($event)) { + + if ($user_id != -1 && !$this->checkItemStatus($event)) { $perm_status = false; } } else { $perm_status = false; } - + if (!$perm_status) { // when no permission to view item -> redirect to no pemrission template trigger_error('ItemLoad Permission Failed for prefix ['.$event->getPrefixSpecial().']', E_USER_WARNING); @@ -522,7 +527,7 @@ $sql = $this->Application->ReplaceLanguageTags($sql); $object->setSelectSQL($sql); $object->Counted = false; // when requery="1" should re-count records too! - + $object->linkToParent( $this->getMainSpecial($event) ); $this->AddFilters($event); @@ -1044,7 +1049,7 @@ { $object =& $event->getObject( Array('skip_autoload' => true) ); /* @var $object kDBItem */ - + $object->Clear(0); $this->Application->SetVar($event->Prefix_Special.'_SaveEvent', 'OnCreate'); Index: trunk/core/units/admin/admin_tag_processor.php =================================================================== diff -u -N -r8397 -r8413 --- trunk/core/units/admin/admin_tag_processor.php (.../admin_tag_processor.php) (revision 8397) +++ trunk/core/units/admin/admin_tag_processor.php (.../admin_tag_processor.php) (revision 8413) @@ -746,7 +746,7 @@ list($index_file, $env) = explode('|', $last_template); $vars = $this->Application->HttpQuery->processQueryString($env, 'pass'); - $recursion_templates = Array ('login', 'index'); + $recursion_templates = Array ('login', 'index', 'no_permission'); if (isset($vars['admin']) && $vars['admin'] == 1) { // index template doesn't begin recursion on front-end (in admin frame) Index: trunk/core/admin_templates/no_permission.tpl =================================================================== diff -u -N -r8397 -r8413 --- trunk/core/admin_templates/no_permission.tpl (.../no_permission.tpl) (revision 8397) +++ trunk/core/admin_templates/no_permission.tpl (.../no_permission.tpl) (revision 8413) @@ -1,4 +1,5 @@ +
@@ -91,9 +91,9 @@ function FieldID($field_name) { var $field_mask = ''; - return $field_mask.replace('#FIELD#', $field_name); + return $field_mask.replace('#FIELD#', $field_name); } - + function toggle_fullsize() { if (document.getElementById('_cb_' + FieldID('SameImages')).checked) { document.getElementById(FieldID('LocalImage') + '_0').disabled = true; @@ -108,7 +108,7 @@ document.getElementById(FieldID('Url')).disabled = false; } } - + if (document.getElementById('_cb_' + FieldID('DefaultImg')).checked) { document.getElementById('_cb_' + FieldID('DefaultImg')).disabled = true; document.getElementById('_cb_' + FieldID('Enabled')).disabled = true; @@ -120,7 +120,7 @@ document.getElementById(FieldID('Enabled')).value = 1; } } - + function check_primary() { if (!document.getElementById('_cb_' + FieldID('Enabled')).checked) { document.getElementById('_cb_' + FieldID('DefaultImg')).checked = false; @@ -145,7 +145,7 @@ - +