Index: trunk/kernel/units/images/image_event_handler.php =================================================================== diff -u -N --- trunk/kernel/units/images/image_event_handler.php (revision 0) +++ trunk/kernel/units/images/image_event_handler.php (revision 4303) @@ -0,0 +1,336 @@ +'ImageAction', + 'OnBeforeDeleteFromLive'=>'ImageAction', + 'OnBeforeCopyToLive'=>'ImageAction', + 'OnBeforeItemDelete'=>'ImageAction', + 'OnAfterClone'=>'ImageAction', + ); + + $this->eventMethods = array_merge($this->eventMethods, $image_events); + } + + function customProcessing(&$event, $type) + { + $object =& $event->GetObject(); + switch ($type) + { + case 'before' : + if ($object->GetDBField('LocalImage')) + { + $object->SetDBField('Url', ''); + } + else + { + $object->SetDBField('LocalPath', ''); + } + + if ($object->GetDBField('LocalThumb')) + { + $object->SetDBField('ThumbUrl', ''); + } + else + { + $object->SetDBField('ThumbPath', ''); + } + + if ($object->GetDBField('SameImages')) + { + $object->SetDBField('LocalImage', 1); + $object->SetDBField('LocalPath', ''); + $object->SetDBField('Url', ''); + } + break; + case 'after' : + if ($object->GetDBField('DefaultImg') ) + { + $sql = 'UPDATE '.$object->TableName.' SET DefaultImg=0 WHERE ResourceId='. + $object->GetDBField('ResourceId').' AND ImageId<>'. + $object->GetId(); + $res = $this->Conn->Query($sql); + } + break; + default: + } + } + + function ImageAction(&$event) + { + $id = $event->getEventParam('id'); + $object =& $this->Application->recallObject($event->Prefix.'.-item', $event->Prefix); + if (in_array($event->Name, Array('OnBeforeDeleteFromLive','OnAfterClone')) ) { + $object->SwitchToLive(); + } + elseif ($event->Name == 'OnBeforeItemDelete') { + // keep current table + } + else { + $object->SwitchToTemp(); + } + + $object->Load($id); + + $fields = Array('LocalPath' => 'LocalImage', 'ThumbPath' => 'LocalThumb'); + foreach ($fields as $a_field => $mode_field) { + $file = $object->GetField($a_field); + if (!$file) continue; + $source_file = FULL_PATH.$file; + + switch ($event->Name) { + // Copy image files to pending dir and update corresponding fields in temp record + // Checking for existing files and renaming if nessessary - two users may upload same pending files at the same time! + case 'OnAfterCopyToTemp': + $new_file = IMAGES_PENDING_PATH . $this->ValidateFileName(FULL_PATH.IMAGES_PENDING_PATH, basename($file)); + $dest_file = FULL_PATH.$new_file; + copy($source_file, $dest_file); + $object->Fields[$a_field]['skip_empty'] = false; + $object->SetDBField($a_field, $new_file); + break; + + // Copy image files to live dir (checking if fileexists and renameing if nessessary) + // and update corresponding fields in temp record (which gets copied to live automatically) + case 'OnBeforeCopyToLive': + if ( $object->GetDBField($mode_field) ) { // if image is local + // rename file if it exists in live folder + $new_file = IMAGES_PATH . $this->ValidateFileName(FULL_PATH.IMAGES_PATH, basename($file)); + $dest_file = FULL_PATH.$new_file; + rename($source_file, $dest_file); + } + else { // if image is remote url - remove local file (if any), update local file field with empty value + if (file_exists($source_file)) @unlink($source_file); + $new_file = ''; + } + $object->Fields[$a_field]['skip_empty'] = false; + $object->SetDBField($a_field, $new_file); + break; + + case 'OnBeforeDeleteFromLive': // Delete image files from live folder before copying over from temp + case 'OnBeforeItemDelete': // Delete image files when deleteing Image object + @unlink(FULL_PATH.$file); + break; + + case 'OnAfterClone': // Copy files when cloning objects, renaming it on the fly + $path_info = pathinfo($file); + $new_file = $path_info['dirname'].'/'.$this->ValidateFileName(FULL_PATH.$path_info['dirname'], $path_info['basename']); + $dest_file = FULL_PATH . $new_file; + copy($source_file, $dest_file); + $object->Fields[$a_field]['skip_empty'] = false; + $object->SetDBField($a_field, $new_file); + break; + } + } + if ( in_array($event->Name, Array('OnAfterClone', 'OnBeforeCopyToLive', 'OnAfterCopyToTemp')) ) { + $object->Update(null, true); + } + } + + function ValidateFileName($path, $name) + { + $parts = pathinfo($name); + $ext = '.'.$parts['extension']; + $filename = substr($parts['basename'], 0, -strlen($ext)); + $new_name = $filename.$ext; + while ( file_exists($path.'/'.$new_name) ) + { + if ( preg_match("/({$filename}_)([0-9]*)($ext)/", $new_name, $regs) ) { + $new_name = $regs[1].($regs[2]+1).$regs[3]; + } + else { + $new_name = $filename.'_1'.$ext; + } + } + return $new_name; + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnSetPrimary(&$event) + { + $object =& $event->getObject(); + $object->SetDBField('DefaultImg', 1); + $object->Update(); + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnBeforeItemUpdate(&$event) + { + $object =& $event->getObject(); +// $parent_info = $object->getLinkedInfo(); + $id = $object->GetDBField('ResourceId'); +// $id = $parent_info['ParentId'] ? $parent_info['ParentId'] : $this->Application->GetVar('p_id'); + $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE ResourceId='.$id.' AND DefaultImg=1'; + if(!$this->Conn->GetOne($sql)) + { + $object->SetDBField('DefaultImg', 1); + } + if($object->GetDBField('DefaultImg') && $object->Validate()) + { + + $sql = 'UPDATE '.$object->TableName.' + SET DefaultImg = 0 + WHERE ResourceId = '.$id.' AND ImageId <> '.$object->GetDBField('ImageId'); + $this->Conn->Query($sql); + $object->SetDBField('Enabled', 1); + } + } + + function OnAfterItemCreate(&$event) + { + $event->CallSubEvent('OnBeforeItemUpdate'); + $object =& $event->getObject(); + $object->Update(); + } + + /** + * Deletes all selected items. + * Automatically recurse into sub-items using temp handler, and deletes sub-items + * by calling its Delete method if sub-item has AutoDelete set to true in its config file + * + * @param kEvent $event + */ + function OnMassDelete(&$event) + { + $event->status=erSUCCESS; + + $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); + + $this->StoreSelectedIDs($event); + + $event->setEventParam('ids', $this->getSelectedIDs($event) ); + $this->customProcessing($event, 'before'); + $ids = $event->getEventParam('ids'); + + $object =& $event->getObject(); + $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE DefaultImg=1'; + $primary = $this->Conn->GetOne($sql); + if( $primary && ($key = array_search($primary, $ids)) ) + { + $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE DefaultImg=0'; + $res = $this->Conn->Query($sql); + if($res) + { + unset($ids[$key]); + } + } + + if($ids) + { + $temp->DeleteItems($event->Prefix, $event->Special, $ids); + } + $this->clearSelectedIDs($event); + } + + /*function OnAfterItemLoad(&$event) + { + $object =& $event->getObject(); + + if ( $object->GetDBField('ThumbPath') || $object->GetDBField('SameImages') ) + { + // return local image or url + $path = $object->GetDBField('LocalThumb') ? PROTOCOL.SERVER_NAME.BASE_PATH.$object->GetDBField('ThumbPath') : $object->GetDBField('ThumbUrl'); + if ( $object->GetDBField('LocalThumb') && !file_exists(FULL_PATH.$object->GetDBField('ThumbPath')) ) $path = ''; + } + else { // if we need full which is not the same as thumb + $path = $object->GetDBField('LocalImage') ? PROTOCOL.SERVER_NAME.BASE_PATH.$object->GetDBField('LocalPath') : $object->GetDBField('Url'); + if ( $object->GetDBField('LocalImage') && !file_exists(FULL_PATH.$object->GetDBField('LocalPath')) ) $path = ''; + } + + $object->SetDBField('ImageUrl', $path); + }*/ + + function SetCustomQuery(&$event) + { + parent::SetCustomQuery($event); + + $types=$event->getEventParam('types'); + $except_types=$event->getEventParam('except'); + $object =& $event->getObject(); + $type_clauses = Array(); + + if( !$this->Application->IsAdmin() ) + { + $object->addFilter('active', '%1$s.Enabled = 1'); + } + + if($product_id = $event->getEventParam('product_id')) + { + $object->removeFilter('parent_filter'); + $sql = 'SELECT ResourceId FROM '.$this->Application->getUnitOption('p', 'TableName').' + WHERE ProductId = '.$product_id; + $resource_id = (int) $this->Conn->GetOne($sql); + $object->addFilter('product_images', '%1$s.ResourceId = '.$resource_id); + } + + $type_clauses['additional']['include'] = '%1$s.DefaultImg != 1'; + $type_clauses['additional']['except'] = '%1$s.DefaultImg = 1'; + $type_clauses['additional']['having_filter'] = false; + + /********************************************/ + + $includes_or_filter =& $this->Application->makeClass('kMultipleFilter'); + $includes_or_filter->setType(FLT_TYPE_OR); + + $excepts_and_filter =& $this->Application->makeClass('kMultipleFilter'); + $excepts_and_filter->setType(FLT_TYPE_AND); + + $includes_or_filter_h =& $this->Application->makeClass('kMultipleFilter'); + $includes_or_filter_h->setType(FLT_TYPE_OR); + + $excepts_and_filter_h =& $this->Application->makeClass('kMultipleFilter'); + $excepts_and_filter_h->setType(FLT_TYPE_AND); + + $except_types_array=explode(',', $types); + + if ($types){ + $types_array=explode(',', $types); + for ($i=0; $iremoveFilter('filter_'.$type); + $includes_or_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['include']); + }else{ + $includes_or_filter->removeFilter('filter_'.$type); + $includes_or_filter->addFilter('filter_'.$type, $type_clauses[$type]['include']); + } + } + } + } + + if ($except_types){ + $except_types_array=explode(',', $except_types); + for ($i=0; $iremoveFilter('filter_'.$type); + $excepts_and_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['except']); + }else{ + $excepts_and_filter->removeFilter('filter_'.$type); + $excepts_and_filter->addFilter('filter_'.$type, $type_clauses[$type]['except']); + } + } + } + } + + $object->addFilter('includes_filter', $includes_or_filter); + $object->addFilter('excepts_filter', $excepts_and_filter); + + $object->addFilter('includes_filter_h', $includes_or_filter_h, HAVING_FILTER); + $object->addFilter('excepts_filter_h', $excepts_and_filter_h, HAVING_FILTER); + } +} + +?> \ No newline at end of file Index: trunk/core/units/images/image_tag_processor.php =================================================================== diff -u -N --- trunk/core/units/images/image_tag_processor.php (revision 0) +++ trunk/core/units/images/image_tag_processor.php (revision 4303) @@ -0,0 +1,206 @@ +ImageSrc($params); + $params['img_size'] = $this->ImageSize($params); + if (!$params['img_size']){ + $params['img_size'] = ' width="'.getArrayValue($params, 'DefaultWidth').'"'; + } + $object =& $this->Application->recallObject($this->getPrefixSpecial(), null); + $params['alt'] = htmlspecialchars($object->GetField('AltName')); + $params['name'] = $this->SelectParam($params, 'block,render_as'); + + return $this->Application->ParseBlock($params); + } + + function ItemImage($params) + { + $this->LoadItemImage($params); + $params['img_path'] = $this->ImageSrc($params); + $params['img_size'] = $this->ImageSize($params); + if (!$params['img_size']){ + if (isset($params['DefaultWidth'])) { + $params['img_size'] = ' width="'.getArrayValue($params, 'DefaultWidth').'"'; + } + } + $params['name'] = $this->SelectParam($params, 'render_as,block'); + $object =& $this->Application->recallObject($this->getPrefixSpecial()); + if ( !$object->isLoaded() && !$this->SelectParam($params, 'default_image,DefaultImage') ) return false; + + $params['alt'] = htmlspecialchars($object->GetField('AltName')); + return $this->Application->ParseBlock($params); + } + + function LargeImageExists($params) { + $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); + if ( $object->GetDBField('SameImages') == null || $object->GetDBField('SameImages')=='1' ) + { + return false; + } + else + { + return true; + } + } + + function LoadItemImage($params) + { + $parent_item =& $this->Application->recallObject($params['PrefixSpecial']); + + $this->Application->setUnitOption($this->Prefix,'AutoLoad',false); + $object =& $this->Application->recallObject($this->getPrefixSpecial(), null); + + // if we need primary thumbnail which is preloaded with products list + $object->Clear(); + + // if we need primary thumbnail which is preloaded with products list + if ( + $this->SelectParam($params, 'thumbnail,Thumbnail') && + ( + ( + $this->SelectParam($params, 'primary,Primary') + || + !isset($params['name']) + ) + && + !$this->Application->GetVar('img_id') + && + isset($parent_item->Fields['LocalThumb']) + ) + ) + { + $object->SetDefaultValues(); + $object->SetDBFieldsFromHash($parent_item->GetFieldValues(), Array('SameImages', 'LocalThumb', 'ThumbPath', 'ThumbUrl', 'LocalImage', 'LocalPath', 'Url') ); + $object->Loaded = true; + } + else { // if requested image is not primary thumbnail - load it directly + $id_field = $this->Application->getUnitOption($this->Prefix, 'ForeignKey'); + $parent_table_key = $this->Application->getUnitOption($this->Prefix, 'ParentTableKey'); + + $keys[$id_field] = $parent_item->GetDBField($parent_table_key); + + // which image to load? + if ( getArrayValue($params, 'Primary') ) { //load primary image + $keys['DefaultImg'] = 1; + } + elseif ( getArrayValue($params, 'name') ) { //load by name + $keys['Name'] = $params['name']; + } + elseif ( $image_id = $this->Application->GetVar($this->Prefix.'_id') ) { + $keys['ImageId'] = $image_id; + } + else { + $keys['DefaultImg'] = 1; //if primary was not set explicity and name was also not passed - load primary + } + + $object->Load($keys); + } + } + + function ImageSrc($params) + { + $object =& $this->Application->recallObject($this->getPrefixSpecial(), null); + $ret = ''; + // if we need thumb, or full image is same as thumb + if ( $this->SelectParam($params, 'thumbnail,Thumbnail') || $object->GetDBField('SameImages') ) + { + // return local image or url + $ret = $object->GetDBField('LocalThumb') ? PROTOCOL.SERVER_NAME.BASE_PATH.'/'.$object->GetDBField('ThumbPath') : $object->GetDBField('ThumbUrl'); + if ( $object->GetDBField('LocalThumb') && !file_exists(FULL_PATH.'/'.$object->GetDBField('ThumbPath')) ) $ret = ''; + } + else { // if we need full which is not the same as thumb + $ret = $object->GetDBField('LocalImage') ? PROTOCOL.SERVER_NAME.BASE_PATH.'/'.$object->GetDBField('LocalPath') : $object->GetDBField('Url'); + if ( $object->GetDBField('LocalImage') && !file_exists(FULL_PATH.'/'.$object->GetDBField('LocalPath')) ) $ret = ''; + } + + return ($ret && $ret != PROTOCOL.SERVER_NAME.BASE_PATH && $ret != PROTOCOL.SERVER_NAME.BASE_PATH.'/') ? $ret : PROTOCOL.SERVER_NAME.BASE_PATH.THEMES_PATH.'/'.$this->SelectParam($params, 'default_image,DefaultImage'); + } + + function GetFullPath($path) + { + if(!$path) return $path; + + // absolute url + if( preg_match('/^(.*):\/\/(.*)$/U', $path) ) + { + if(strpos($path, PROTOCOL.SERVER_NAME.BASE_PATH) === 0) + { + $path = str_replace(PROTOCOL.SERVER_NAME.BASE_PATH, FULL_PATH.'/', $path); + } + return $path; + } + + // relative url + return FULL_PATH.'/'.substr(THEMES_PATH,1).'/'.$path; + } + + /** + * Makes size clause for img tag, such as + * ' width="80" height="100"' according to max_width + * and max_heght limits. + * + * @param array $params + * @return string + */ + function ImageSize($params) + { + $img_path = $this->GetFullPath( getArrayValue($params, 'img_path') ); + + $image_info = @getimagesize($img_path); + +// if( !($img_path && file_exists($img_path) && isset($image_info) ) ) + if( !$image_info ) + { + trigger_error('Image '.$img_path.' missing or invalid', E_USER_WARNING); + return false; + } + + $orig_width = getArrayValue($image_info, 0); + $orig_height = getArrayValue($image_info, 1); + $max_width = getArrayValue($params, 'MaxWidth'); + $max_height = getArrayValue($params, 'MaxHeight'); + + $too_large = is_numeric($max_width) ? ($orig_width > $max_width) : false; + $too_large = $too_large || (is_numeric($max_height) ? ($orig_height > $max_height) : false); + + if($too_large) + { + $width_ratio = $max_width ? $max_width / $orig_width : 1; + $height_ratio = $max_height ? $max_height / $orig_height : 1; + $ratio = min($width_ratio, $height_ratio); + + $width = ceil($orig_width * $ratio); + $height = ceil($orig_height * $ratio); + } + else + { + $width = $orig_width; + $height = $orig_height; + } + + $size_clause = ' width="'.$width.'" height="'.$height.'"'; + return $size_clause; + } + + + // used in admin + function ImageUrl($params) + { + $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); + if ($object->GetDBField('SameImages') ? $object->GetDBField('LocalThumb') : $object->GetDBField('LocalImage') ) + { + $ret = $this->Application->Phrase(getArrayValue($params,'local_phrase')); + } + else + { + $ret = $object->GetDBField('SameImages') ? $object->GetDBField('ThumbUrl') : $object->GetDBField('Url'); + } + return $ret; + } + +} + +?> \ No newline at end of file Index: trunk/core/units/relationship/relationship_config.php =================================================================== diff -u -N --- trunk/core/units/relationship/relationship_config.php (revision 0) +++ trunk/core/units/relationship/relationship_config.php (revision 4303) @@ -0,0 +1,97 @@ + 'rel', + 'ItemClass' => Array('class'=>'kDBItem','file'=>'','build_event'=>'OnItemBuild'), + 'ListClass' => Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'), + 'EventHandlerClass' => Array('class'=>'RelationshipEventHandler','file'=>'relationship_event_handler.php','build_event'=>'OnBuild'), + 'TagProcessorClass' => Array('class'=>'kDBTagProcessor','file'=>'','build_event'=>'OnBuild'), + 'AutoLoad' => true, + 'Hooks' => Array( + Array( + 'Mode' => hAFTER, + 'Conditional' => false, + 'HookToPrefix' => 'p', + 'HookToSpecial' => '-item', + 'HookToEvent' => Array('OnAfterItemDelete'), + 'DoPrefix' => '', + 'DoSpecial' => '', + 'DoEvent' => 'OnDeleteForeignRelations', + ), + ), + 'QueryString' => Array( + 1 => 'id', + 2 => 'page', + 3 => 'event', + ), + 'IDField' => 'RelationshipId', + 'StatusField' => Array('Enabled','Type'), + 'TableName' => TABLE_PREFIX.'Relationship', + 'ParentTableKey'=> 'ResourceId', + 'ForeignKey' => 'SourceId', + 'ParentPrefix' => 'p', + 'AutoDelete' => true, + 'AutoClone' => true, + + 'FilterMenu' => Array( + 'Groups' => Array( + Array('mode' => 'AND', 'filters' => Array('show_active','show_disabled'), 'type' => WHERE_FILTER), + Array('mode' => 'AND', 'filters' => Array('show_recip','show_oneway'), 'type' => WHERE_FILTER), + ), + 'Filters' => Array( + 'show_active' => Array('label' =>'la_Active', 'on_sql' => '', 'off_sql' => 'Enabled != 1' ), + 'show_disabled' => Array('label' => 'la_Disabled', 'on_sql' => '', 'off_sql' => 'Enabled != 0' ), + 's1' => Array(), + 'show_recip' => Array('label' => 'la_Reciprocal', 'on_sql' => '', 'off_sql' => '%1$s.Type != 1' ), + 'show_oneway' => Array('label' => 'la_OneWay', 'on_sql' => '', 'off_sql' => '%1$s.Type != 2' ), + ) + ), + + 'CalculatedFields' => Array( + '' => Array( + 'ItemName' => 'TRIM(CONCAT(#ITEM_NAMES#))', + 'ItemType' => '#ITEM_TYPES#', + ), + ), + + 'ListSQLs' => Array( ''=> 'SELECT %1$s.RelationshipId, %1$s.Priority, %1$s.Type, %1$s.Enabled %2$s + FROM %1$s #ITEM_JOIN#', + ), // key - special, value - list select sql + + 'ListSortings' => Array( + '' => Array( + 'ForcedSorting' => Array('Priority' => 'desc'), + 'Sorting' => Array('ItemName' => 'asc', 'ItemType' => 'asc'), + ) + ), + 'ItemSQLs' => Array( '' => 'SELECT %1$s.* %2$s FROM %1$s #ITEM_JOIN#',), + + 'Fields' => Array( + 'RelationshipId' => Array(), + 'SourceId' => Array('type'=>'int'), + 'TargetId' => Array('type'=>'int'), + 'SourceType' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'TargetType' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'Type' => Array('type'=>'int','formatter'=>'kOptionsFormatter','options'=>Array(1=>'la_Reciprocal',0=>'la_OneWay'),'not_null'=>1,'default'=>0,'use_phrases'=>1), + 'Enabled' => Array('type'=>'int','formatter'=>'kOptionsFormatter','options'=>Array(0=>'la_Disabled',1=>'la_Enabled'),'not_null'=>1,'default'=>1,'use_phrases'=>1), + 'Priority' => Array('type'=>'int','not_null'=>1,'default'=>0), + ), + 'VirtualFields' => Array( 'ItemName' => Array(), + 'ItemType' => Array(), + ), + + 'Grids' => Array( + 'Default' => Array( + 'Icons' => Array('default'=>'icon16_custom.gif','1_0'=>'icon16_relation_one-way.gif','0_0'=>'icon16_relation_one-way_disabled.gif','1_1'=>'icon16_relation_reciprocal.gif','0_1'=>'icon16_relation_reciprocal_disabled.gif'), // icons for each StatusField values, if no matches or no statusfield selected, then "default" icon is used + 'Fields' => Array( + 'ItemName' => Array( 'title'=>'la_col_TargetId', 'data_block' => 'grid_checkbox_td'), + 'ItemType' => Array( 'title'=>'la_col_TargetType' ), + 'Type' => Array( 'title'=>'la_col_RelationshipType' ), + 'Enabled' => Array( 'title'=>'la_col_Status' ), + ), + + ), + ), + ); + +?> \ No newline at end of file Index: trunk/core/units/images/images_config.php =================================================================== diff -u -N --- trunk/core/units/images/images_config.php (revision 0) +++ trunk/core/units/images/images_config.php (revision 4303) @@ -0,0 +1,155 @@ + 'img', + 'Clones' => Array( + 'catimg' => Array( + 'ParentPrefix' => 'c', + 'AggregateTags' => Array( + Array( + 'AggregateTo' => 'c', + 'AggregatedTagName' => 'Image', + 'LocalTagName' => 'ItemImage', + ), + Array( + 'AggregateTo' => 'c', + 'AggregatedTagName' => 'ListImages', + 'LocalTagName' => 'PrintList2', + 'LocalSpecial' => 'list', + ), + Array( + 'AggregateTo' => 'c', + 'AggregatedTagName' => 'LargeImageExists', + 'LocalTagName' => 'LargeImageExists', + ), + ), + ) + ), + 'ItemClass' => Array('class'=>'kDBItem','file'=>'','build_event'=>'OnItemBuild'), + 'ListClass' => Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'), + 'EventHandlerClass' => Array('class'=>'ImageEventHandler','file'=>'image_event_handler.php','build_event'=>'OnBuild'), + 'TagProcessorClass' => Array('class'=>'ImageTagProcessor','file'=>'image_tag_processor.php','build_event'=>'OnBuild'), + 'AutoLoad' => true, + 'hooks' => Array(), + 'AggregateTags' => Array( + Array( + 'AggregateTo' => 'p', + 'AggregatedTagName' => 'Image', + 'LocalTagName' => 'ItemImage', + ), + Array( + 'AggregateTo' => 'p', + 'AggregatedTagName' => 'ListImages', + 'LocalTagName' => 'PrintList2', + 'LocalSpecial' => 'list', + ), + Array( + 'AggregateTo' => 'p', + 'AggregatedTagName' => 'LargeImageExists', + 'LocalTagName' => 'LargeImageExists', + ), + + ), + 'QueryString' => Array( + 1 => 'id', + 2 => 'page', + 3 => 'event', + ), + 'IDField' => 'ImageId', + 'StatusField' => Array('Enabled', 'DefaultImg'), // field, that is affected by Approve/Decline events + 'TitleField' => 'Name', // field, used in bluebar when editing existing item + 'TableName' => TABLE_PREFIX.'Images', + 'ParentTableKey'=> 'ResourceId', // linked field in master table + 'ForeignKey' => 'ResourceId', // linked field in subtable + 'ParentPrefix' => 'p', + 'AutoDelete' => true, + 'AutoClone' => true, + + 'FilterMenu' => Array( + 'Groups' => Array( + Array('mode' => 'AND', 'filters' => Array('show_active','show_disabled'), 'type' => WHERE_FILTER), + ), + 'Filters' => Array( + 'show_active' => Array('label' =>'la_Active', 'on_sql' => '', 'off_sql' => 'Enabled != 1' ), + 'show_disabled' => Array('label' => 'la_Disabled', 'on_sql' => '', 'off_sql' => 'Enabled != 0' ), + ) + ), + + 'CalculatedFields' => Array( + '' => Array( + 'Preview' => '0', + ), + ), + + 'ListSQLs' => Array( ''=>'SELECT * FROM %s', + ), // key - special, value - list select sql + 'ItemSQLs' => Array( ''=>'SELECT * FROM %s', + ), + 'ListSortings' => Array( + '' => Array( + 'ForcedSorting' => Array('Priority' => 'desc'), + 'Sorting' => Array('Name' => 'asc'), + ) + ), + 'Fields' => Array( + 'ImageId' => Array('type'=>'int'), + 'ResourceId' => Array('type'=>'int', 'not_null'=>1, 'default' => 0), + 'Url' => Array('max_len'=>255, 'default' => '', 'not_null'=>1), + 'Name' => Array('max_len'=>255, 'required'=>1, 'not_null'=>1, 'default' => ''), + 'AltName' => Array('max_len'=>255, 'required'=>1, 'not_null'=>1), + 'ImageIndex' => Array('type'=>'int', 'default' => 0, 'not_null'=>1), + 'LocalImage' => Array('type'=>'int', 'default' => 1, 'not_null'=>1), + 'LocalPath' => Array('formatter'=>'kPictureFormatter', 'skip_empty'=>1, 'max_len'=>240, 'default' => '', 'not_null' => 1, 'include_path' => 1, + 'allowed_types' => Array( + 0 => 'image/jpeg', + 1 => 'image/pjpeg', + 2 => 'image/png', + 3 => 'image/gif', + 4 => 'image/bmp' + ), + 'error_msgs' => Array( 'bad_file_format' => '!la_error_InvalidFileFormat!', + 'bad_file_size' => '!la_error_FileTooLarge!', + 'cant_save_file' => '!la_error_cant_save_file!' + ) + ), + 'Enabled' => Array('formatter'=>'kOptionsFormatter', 'use_phrases' => 1, 'options' => Array ( 1 => 'la_Enabled', 0 => 'la_Disabled' ), 'default' => 0, 'not_null'=>1), + 'DefaultImg' => Array('type'=>'int', 'default' => 0, 'not_null'=>1), + 'ThumbUrl' => Array('max_len' => 255), + 'Priority' => Array('type'=>'int', 'default' => 0, 'not_null'=>1), + 'ThumbPath' => Array( 'formatter'=>'kPictureFormatter', 'skip_empty'=>1, 'max_len' => 255, + 'allowed_types' => Array( + 0 => 'image/jpeg', + 1 => 'image/pjpeg', + 2 => 'image/png', + 3 => 'image/gif', + 4 => 'image/bmp' + ), + 'error_msgs' => Array( 'bad_file_format' => '!la_error_InvalidFileFormat!', + 'bad_file_size' => '!la_error_FileTooLarge!', + 'cant_save_file' => '!la_error_cant_save_file!' + ) + ), + 'LocalThumb' => Array('type'=>'int', 'default' => 1, 'not_null'=>1), + 'SameImages' => Array('type'=>'int', 'default' => 1, 'not_null'=>1), + ), + 'VirtualFields' => Array( + 'Preview' => Array(), + 'ImageUrl' => Array(), + ), + + 'Grids' => Array( + 'Default' => Array( + 'Icons' => Array('default'=>'icon17_custom.gif','1_0'=>'icon16_image.gif','0_0'=>'icon16_image_disabled.gif','1_1'=>'icon16_image_primary.gif'), + 'Fields' => Array( + 'Name' => Array( 'title'=>'la_col_ImageName' , 'data_block' => 'image_caption_td'), + 'AltName' => Array( 'title'=>'la_col_AltName' ), + 'Url' => Array( 'title'=>'la_col_ImageUrl', 'data_block' => 'image_url_td' ), + 'Enabled' => Array( 'title'=>'la_col_ImageEnabled' ), + 'Preview' => Array( 'title'=>'la_col_Preview', 'data_block' => 'image_preview_td' ), + ), + + ), + ), + ); + +?> \ No newline at end of file Index: trunk/kernel/units/images/image_tag_processor.php =================================================================== diff -u -N --- trunk/kernel/units/images/image_tag_processor.php (revision 0) +++ trunk/kernel/units/images/image_tag_processor.php (revision 4303) @@ -0,0 +1,206 @@ +ImageSrc($params); + $params['img_size'] = $this->ImageSize($params); + if (!$params['img_size']){ + $params['img_size'] = ' width="'.getArrayValue($params, 'DefaultWidth').'"'; + } + $object =& $this->Application->recallObject($this->getPrefixSpecial(), null); + $params['alt'] = htmlspecialchars($object->GetField('AltName')); + $params['name'] = $this->SelectParam($params, 'block,render_as'); + + return $this->Application->ParseBlock($params); + } + + function ItemImage($params) + { + $this->LoadItemImage($params); + $params['img_path'] = $this->ImageSrc($params); + $params['img_size'] = $this->ImageSize($params); + if (!$params['img_size']){ + if (isset($params['DefaultWidth'])) { + $params['img_size'] = ' width="'.getArrayValue($params, 'DefaultWidth').'"'; + } + } + $params['name'] = $this->SelectParam($params, 'render_as,block'); + $object =& $this->Application->recallObject($this->getPrefixSpecial()); + if ( !$object->isLoaded() && !$this->SelectParam($params, 'default_image,DefaultImage') ) return false; + + $params['alt'] = htmlspecialchars($object->GetField('AltName')); + return $this->Application->ParseBlock($params); + } + + function LargeImageExists($params) { + $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); + if ( $object->GetDBField('SameImages') == null || $object->GetDBField('SameImages')=='1' ) + { + return false; + } + else + { + return true; + } + } + + function LoadItemImage($params) + { + $parent_item =& $this->Application->recallObject($params['PrefixSpecial']); + + $this->Application->setUnitOption($this->Prefix,'AutoLoad',false); + $object =& $this->Application->recallObject($this->getPrefixSpecial(), null); + + // if we need primary thumbnail which is preloaded with products list + $object->Clear(); + + // if we need primary thumbnail which is preloaded with products list + if ( + $this->SelectParam($params, 'thumbnail,Thumbnail') && + ( + ( + $this->SelectParam($params, 'primary,Primary') + || + !isset($params['name']) + ) + && + !$this->Application->GetVar('img_id') + && + isset($parent_item->Fields['LocalThumb']) + ) + ) + { + $object->SetDefaultValues(); + $object->SetDBFieldsFromHash($parent_item->GetFieldValues(), Array('SameImages', 'LocalThumb', 'ThumbPath', 'ThumbUrl', 'LocalImage', 'LocalPath', 'Url') ); + $object->Loaded = true; + } + else { // if requested image is not primary thumbnail - load it directly + $id_field = $this->Application->getUnitOption($this->Prefix, 'ForeignKey'); + $parent_table_key = $this->Application->getUnitOption($this->Prefix, 'ParentTableKey'); + + $keys[$id_field] = $parent_item->GetDBField($parent_table_key); + + // which image to load? + if ( getArrayValue($params, 'Primary') ) { //load primary image + $keys['DefaultImg'] = 1; + } + elseif ( getArrayValue($params, 'name') ) { //load by name + $keys['Name'] = $params['name']; + } + elseif ( $image_id = $this->Application->GetVar($this->Prefix.'_id') ) { + $keys['ImageId'] = $image_id; + } + else { + $keys['DefaultImg'] = 1; //if primary was not set explicity and name was also not passed - load primary + } + + $object->Load($keys); + } + } + + function ImageSrc($params) + { + $object =& $this->Application->recallObject($this->getPrefixSpecial(), null); + $ret = ''; + // if we need thumb, or full image is same as thumb + if ( $this->SelectParam($params, 'thumbnail,Thumbnail') || $object->GetDBField('SameImages') ) + { + // return local image or url + $ret = $object->GetDBField('LocalThumb') ? PROTOCOL.SERVER_NAME.BASE_PATH.'/'.$object->GetDBField('ThumbPath') : $object->GetDBField('ThumbUrl'); + if ( $object->GetDBField('LocalThumb') && !file_exists(FULL_PATH.'/'.$object->GetDBField('ThumbPath')) ) $ret = ''; + } + else { // if we need full which is not the same as thumb + $ret = $object->GetDBField('LocalImage') ? PROTOCOL.SERVER_NAME.BASE_PATH.'/'.$object->GetDBField('LocalPath') : $object->GetDBField('Url'); + if ( $object->GetDBField('LocalImage') && !file_exists(FULL_PATH.'/'.$object->GetDBField('LocalPath')) ) $ret = ''; + } + + return ($ret && $ret != PROTOCOL.SERVER_NAME.BASE_PATH && $ret != PROTOCOL.SERVER_NAME.BASE_PATH.'/') ? $ret : PROTOCOL.SERVER_NAME.BASE_PATH.THEMES_PATH.'/'.$this->SelectParam($params, 'default_image,DefaultImage'); + } + + function GetFullPath($path) + { + if(!$path) return $path; + + // absolute url + if( preg_match('/^(.*):\/\/(.*)$/U', $path) ) + { + if(strpos($path, PROTOCOL.SERVER_NAME.BASE_PATH) === 0) + { + $path = str_replace(PROTOCOL.SERVER_NAME.BASE_PATH, FULL_PATH.'/', $path); + } + return $path; + } + + // relative url + return FULL_PATH.'/'.substr(THEMES_PATH,1).'/'.$path; + } + + /** + * Makes size clause for img tag, such as + * ' width="80" height="100"' according to max_width + * and max_heght limits. + * + * @param array $params + * @return string + */ + function ImageSize($params) + { + $img_path = $this->GetFullPath( getArrayValue($params, 'img_path') ); + + $image_info = @getimagesize($img_path); + +// if( !($img_path && file_exists($img_path) && isset($image_info) ) ) + if( !$image_info ) + { + trigger_error('Image '.$img_path.' missing or invalid', E_USER_WARNING); + return false; + } + + $orig_width = getArrayValue($image_info, 0); + $orig_height = getArrayValue($image_info, 1); + $max_width = getArrayValue($params, 'MaxWidth'); + $max_height = getArrayValue($params, 'MaxHeight'); + + $too_large = is_numeric($max_width) ? ($orig_width > $max_width) : false; + $too_large = $too_large || (is_numeric($max_height) ? ($orig_height > $max_height) : false); + + if($too_large) + { + $width_ratio = $max_width ? $max_width / $orig_width : 1; + $height_ratio = $max_height ? $max_height / $orig_height : 1; + $ratio = min($width_ratio, $height_ratio); + + $width = ceil($orig_width * $ratio); + $height = ceil($orig_height * $ratio); + } + else + { + $width = $orig_width; + $height = $orig_height; + } + + $size_clause = ' width="'.$width.'" height="'.$height.'"'; + return $size_clause; + } + + + // used in admin + function ImageUrl($params) + { + $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); + if ($object->GetDBField('SameImages') ? $object->GetDBField('LocalThumb') : $object->GetDBField('LocalImage') ) + { + $ret = $this->Application->Phrase(getArrayValue($params,'local_phrase')); + } + else + { + $ret = $object->GetDBField('SameImages') ? $object->GetDBField('ThumbUrl') : $object->GetDBField('Url'); + } + return $ret; + } + +} + +?> \ No newline at end of file Index: trunk/kernel/units/relationship/relationship_config.php =================================================================== diff -u -N --- trunk/kernel/units/relationship/relationship_config.php (revision 0) +++ trunk/kernel/units/relationship/relationship_config.php (revision 4303) @@ -0,0 +1,97 @@ + 'rel', + 'ItemClass' => Array('class'=>'kDBItem','file'=>'','build_event'=>'OnItemBuild'), + 'ListClass' => Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'), + 'EventHandlerClass' => Array('class'=>'RelationshipEventHandler','file'=>'relationship_event_handler.php','build_event'=>'OnBuild'), + 'TagProcessorClass' => Array('class'=>'kDBTagProcessor','file'=>'','build_event'=>'OnBuild'), + 'AutoLoad' => true, + 'Hooks' => Array( + Array( + 'Mode' => hAFTER, + 'Conditional' => false, + 'HookToPrefix' => 'p', + 'HookToSpecial' => '-item', + 'HookToEvent' => Array('OnAfterItemDelete'), + 'DoPrefix' => '', + 'DoSpecial' => '', + 'DoEvent' => 'OnDeleteForeignRelations', + ), + ), + 'QueryString' => Array( + 1 => 'id', + 2 => 'page', + 3 => 'event', + ), + 'IDField' => 'RelationshipId', + 'StatusField' => Array('Enabled','Type'), + 'TableName' => TABLE_PREFIX.'Relationship', + 'ParentTableKey'=> 'ResourceId', + 'ForeignKey' => 'SourceId', + 'ParentPrefix' => 'p', + 'AutoDelete' => true, + 'AutoClone' => true, + + 'FilterMenu' => Array( + 'Groups' => Array( + Array('mode' => 'AND', 'filters' => Array('show_active','show_disabled'), 'type' => WHERE_FILTER), + Array('mode' => 'AND', 'filters' => Array('show_recip','show_oneway'), 'type' => WHERE_FILTER), + ), + 'Filters' => Array( + 'show_active' => Array('label' =>'la_Active', 'on_sql' => '', 'off_sql' => 'Enabled != 1' ), + 'show_disabled' => Array('label' => 'la_Disabled', 'on_sql' => '', 'off_sql' => 'Enabled != 0' ), + 's1' => Array(), + 'show_recip' => Array('label' => 'la_Reciprocal', 'on_sql' => '', 'off_sql' => '%1$s.Type != 1' ), + 'show_oneway' => Array('label' => 'la_OneWay', 'on_sql' => '', 'off_sql' => '%1$s.Type != 2' ), + ) + ), + + 'CalculatedFields' => Array( + '' => Array( + 'ItemName' => 'TRIM(CONCAT(#ITEM_NAMES#))', + 'ItemType' => '#ITEM_TYPES#', + ), + ), + + 'ListSQLs' => Array( ''=> 'SELECT %1$s.RelationshipId, %1$s.Priority, %1$s.Type, %1$s.Enabled %2$s + FROM %1$s #ITEM_JOIN#', + ), // key - special, value - list select sql + + 'ListSortings' => Array( + '' => Array( + 'ForcedSorting' => Array('Priority' => 'desc'), + 'Sorting' => Array('ItemName' => 'asc', 'ItemType' => 'asc'), + ) + ), + 'ItemSQLs' => Array( '' => 'SELECT %1$s.* %2$s FROM %1$s #ITEM_JOIN#',), + + 'Fields' => Array( + 'RelationshipId' => Array(), + 'SourceId' => Array('type'=>'int'), + 'TargetId' => Array('type'=>'int'), + 'SourceType' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'TargetType' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'Type' => Array('type'=>'int','formatter'=>'kOptionsFormatter','options'=>Array(1=>'la_Reciprocal',0=>'la_OneWay'),'not_null'=>1,'default'=>0,'use_phrases'=>1), + 'Enabled' => Array('type'=>'int','formatter'=>'kOptionsFormatter','options'=>Array(0=>'la_Disabled',1=>'la_Enabled'),'not_null'=>1,'default'=>1,'use_phrases'=>1), + 'Priority' => Array('type'=>'int','not_null'=>1,'default'=>0), + ), + 'VirtualFields' => Array( 'ItemName' => Array(), + 'ItemType' => Array(), + ), + + 'Grids' => Array( + 'Default' => Array( + 'Icons' => Array('default'=>'icon16_custom.gif','1_0'=>'icon16_relation_one-way.gif','0_0'=>'icon16_relation_one-way_disabled.gif','1_1'=>'icon16_relation_reciprocal.gif','0_1'=>'icon16_relation_reciprocal_disabled.gif'), // icons for each StatusField values, if no matches or no statusfield selected, then "default" icon is used + 'Fields' => Array( + 'ItemName' => Array( 'title'=>'la_col_TargetId', 'data_block' => 'grid_checkbox_td'), + 'ItemType' => Array( 'title'=>'la_col_TargetType' ), + 'Type' => Array( 'title'=>'la_col_RelationshipType' ), + 'Enabled' => Array( 'title'=>'la_col_Status' ), + ), + + ), + ), + ); + +?> \ No newline at end of file Index: trunk/kernel/units/images/images_config.php =================================================================== diff -u -N --- trunk/kernel/units/images/images_config.php (revision 0) +++ trunk/kernel/units/images/images_config.php (revision 4303) @@ -0,0 +1,155 @@ + 'img', + 'Clones' => Array( + 'catimg' => Array( + 'ParentPrefix' => 'c', + 'AggregateTags' => Array( + Array( + 'AggregateTo' => 'c', + 'AggregatedTagName' => 'Image', + 'LocalTagName' => 'ItemImage', + ), + Array( + 'AggregateTo' => 'c', + 'AggregatedTagName' => 'ListImages', + 'LocalTagName' => 'PrintList2', + 'LocalSpecial' => 'list', + ), + Array( + 'AggregateTo' => 'c', + 'AggregatedTagName' => 'LargeImageExists', + 'LocalTagName' => 'LargeImageExists', + ), + ), + ) + ), + 'ItemClass' => Array('class'=>'kDBItem','file'=>'','build_event'=>'OnItemBuild'), + 'ListClass' => Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'), + 'EventHandlerClass' => Array('class'=>'ImageEventHandler','file'=>'image_event_handler.php','build_event'=>'OnBuild'), + 'TagProcessorClass' => Array('class'=>'ImageTagProcessor','file'=>'image_tag_processor.php','build_event'=>'OnBuild'), + 'AutoLoad' => true, + 'hooks' => Array(), + 'AggregateTags' => Array( + Array( + 'AggregateTo' => 'p', + 'AggregatedTagName' => 'Image', + 'LocalTagName' => 'ItemImage', + ), + Array( + 'AggregateTo' => 'p', + 'AggregatedTagName' => 'ListImages', + 'LocalTagName' => 'PrintList2', + 'LocalSpecial' => 'list', + ), + Array( + 'AggregateTo' => 'p', + 'AggregatedTagName' => 'LargeImageExists', + 'LocalTagName' => 'LargeImageExists', + ), + + ), + 'QueryString' => Array( + 1 => 'id', + 2 => 'page', + 3 => 'event', + ), + 'IDField' => 'ImageId', + 'StatusField' => Array('Enabled', 'DefaultImg'), // field, that is affected by Approve/Decline events + 'TitleField' => 'Name', // field, used in bluebar when editing existing item + 'TableName' => TABLE_PREFIX.'Images', + 'ParentTableKey'=> 'ResourceId', // linked field in master table + 'ForeignKey' => 'ResourceId', // linked field in subtable + 'ParentPrefix' => 'p', + 'AutoDelete' => true, + 'AutoClone' => true, + + 'FilterMenu' => Array( + 'Groups' => Array( + Array('mode' => 'AND', 'filters' => Array('show_active','show_disabled'), 'type' => WHERE_FILTER), + ), + 'Filters' => Array( + 'show_active' => Array('label' =>'la_Active', 'on_sql' => '', 'off_sql' => 'Enabled != 1' ), + 'show_disabled' => Array('label' => 'la_Disabled', 'on_sql' => '', 'off_sql' => 'Enabled != 0' ), + ) + ), + + 'CalculatedFields' => Array( + '' => Array( + 'Preview' => '0', + ), + ), + + 'ListSQLs' => Array( ''=>'SELECT * FROM %s', + ), // key - special, value - list select sql + 'ItemSQLs' => Array( ''=>'SELECT * FROM %s', + ), + 'ListSortings' => Array( + '' => Array( + 'ForcedSorting' => Array('Priority' => 'desc'), + 'Sorting' => Array('Name' => 'asc'), + ) + ), + 'Fields' => Array( + 'ImageId' => Array('type'=>'int'), + 'ResourceId' => Array('type'=>'int', 'not_null'=>1, 'default' => 0), + 'Url' => Array('max_len'=>255, 'default' => '', 'not_null'=>1), + 'Name' => Array('max_len'=>255, 'required'=>1, 'not_null'=>1, 'default' => ''), + 'AltName' => Array('max_len'=>255, 'required'=>1, 'not_null'=>1), + 'ImageIndex' => Array('type'=>'int', 'default' => 0, 'not_null'=>1), + 'LocalImage' => Array('type'=>'int', 'default' => 1, 'not_null'=>1), + 'LocalPath' => Array('formatter'=>'kPictureFormatter', 'skip_empty'=>1, 'max_len'=>240, 'default' => '', 'not_null' => 1, 'include_path' => 1, + 'allowed_types' => Array( + 0 => 'image/jpeg', + 1 => 'image/pjpeg', + 2 => 'image/png', + 3 => 'image/gif', + 4 => 'image/bmp' + ), + 'error_msgs' => Array( 'bad_file_format' => '!la_error_InvalidFileFormat!', + 'bad_file_size' => '!la_error_FileTooLarge!', + 'cant_save_file' => '!la_error_cant_save_file!' + ) + ), + 'Enabled' => Array('formatter'=>'kOptionsFormatter', 'use_phrases' => 1, 'options' => Array ( 1 => 'la_Enabled', 0 => 'la_Disabled' ), 'default' => 0, 'not_null'=>1), + 'DefaultImg' => Array('type'=>'int', 'default' => 0, 'not_null'=>1), + 'ThumbUrl' => Array('max_len' => 255), + 'Priority' => Array('type'=>'int', 'default' => 0, 'not_null'=>1), + 'ThumbPath' => Array( 'formatter'=>'kPictureFormatter', 'skip_empty'=>1, 'max_len' => 255, + 'allowed_types' => Array( + 0 => 'image/jpeg', + 1 => 'image/pjpeg', + 2 => 'image/png', + 3 => 'image/gif', + 4 => 'image/bmp' + ), + 'error_msgs' => Array( 'bad_file_format' => '!la_error_InvalidFileFormat!', + 'bad_file_size' => '!la_error_FileTooLarge!', + 'cant_save_file' => '!la_error_cant_save_file!' + ) + ), + 'LocalThumb' => Array('type'=>'int', 'default' => 1, 'not_null'=>1), + 'SameImages' => Array('type'=>'int', 'default' => 1, 'not_null'=>1), + ), + 'VirtualFields' => Array( + 'Preview' => Array(), + 'ImageUrl' => Array(), + ), + + 'Grids' => Array( + 'Default' => Array( + 'Icons' => Array('default'=>'icon17_custom.gif','1_0'=>'icon16_image.gif','0_0'=>'icon16_image_disabled.gif','1_1'=>'icon16_image_primary.gif'), + 'Fields' => Array( + 'Name' => Array( 'title'=>'la_col_ImageName' , 'data_block' => 'image_caption_td'), + 'AltName' => Array( 'title'=>'la_col_AltName' ), + 'Url' => Array( 'title'=>'la_col_ImageUrl', 'data_block' => 'image_url_td' ), + 'Enabled' => Array( 'title'=>'la_col_ImageEnabled' ), + 'Preview' => Array( 'title'=>'la_col_Preview', 'data_block' => 'image_preview_td' ), + ), + + ), + ), + ); + +?> \ No newline at end of file Index: trunk/kernel/units/reviews/reviews_event_handler.php =================================================================== diff -u -N --- trunk/kernel/units/reviews/reviews_event_handler.php (revision 0) +++ trunk/kernel/units/reviews/reviews_event_handler.php (revision 4303) @@ -0,0 +1,142 @@ +getObject(); + switch ($event->Special) + { + case 'showall': + $object->clearFilters(); + break; + + case 'products': + $object->removeFilter('parent_filter'); // this is important + $object->addFilter('product_reviews', '%1$s.ItemId = pr.ResourceId'); + // $object->addFilter('active', '%1$s.Status = 1'); + + /*$this->Application->setUnitOption('p', 'AutoLoad', true); + $product =& $this->Application->recallObject('p'); + $object->addFilter('current_product', 'pr.ResourceId = '.$product->GetDBField('ResourceId'));*/ + break; + + case 'product': + $object->clearFilters(); + $object->addFilter('product_reviews', '%1$s.ItemId = pr.ResourceId'); + $object->addFilter('active', '%1$s.Status = 1'); + $this->Application->setUnitOption('p', 'AutoLoad', true); + $product =& $this->Application->recallObject('p'); + $object->addFilter('current_product', 'pr.ResourceId = '.$product->GetDBField('ResourceId')); + + break; + } + + if($event->getEventParam('type') == 'current_user') + { + $user_id = $this->Application->GetVar('u_id') ? $this->Application->GetVar('u_id') : -2; + $ip = $_SERVER['REMOTE_ADDR']; + $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $event->getObject(); + $product_info = $object->getLinkedInfo(); + $object->addFilter('current_item', '%1$s.ItemId = '.$product_info['ParentId']); + $object->addFilter('current_user', '%1$s.CreatedById = '.$user_id); + $object->addFilter('current_ip', '%1$s.IPAddress = "'.$ip.'"'); + + } + } + + /** + * Adds review from front in case if user is logged in + * + * @param kEvent $event + */ + function OnAddReview(&$event) + { + $user_id = ($this->Application->GetVar('u_id') == 0) ? -2 : $this->Application->GetVar('u_id'); + $event->redirect_params = Array('pass' => 'all,p'); + + $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $event->getObject(); + $item_info = $this->Application->GetVar('rev_product'); + $product_info = $object->getLinkedInfo(); + + $sql = ' SELECT * FROM '.TABLE_PREFIX.'SpamControl + WHERE ItemResourceId='.$product_info['ParentId'].' + AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'" + AND PortalUserId='.$user_id.' + AND DataType="Review"'; + $res = $this->Conn->GetRow($sql); + + if( $res && $res['Expire'] < adodb_mktime() ) + { + $sql = ' DELETE FROM '.TABLE_PREFIX.'SpamControl + WHERE ItemResourceId='.$product_info['ParentId'].' + AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'" + AND PortalUserId='.$user_id.' + AND DataType="Review"'; + $this->Conn->Query($sql); + unset($res); + } + + if(!$res) + { + $object->SetFieldsFromHash( array_shift($item_info) ); + $object->SetDBField('CreatedById', $user_id); + $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']); + $object->SetDBField('CreatedOn', adodb_mktime()); + + if( $this->Application->CheckPermission('PRODUCT.REVIEW.PENDING') ) + { + $object->SetDBField('Status', 2); + } + elseif( $this->Application->CheckPermission('PRODUCT.REVIEW') ) + { + $object->SetDBField('Status', 1); + } + + $object->SetDBField('ItemId', $product_info['ParentId']); + + $event->CallSubEvent('OnCreate'); + + if($event->status == erSUCCESS) + { + $product_object =& $this->Application->recallObject('p'); + $sql = ' SELECT COUNT(ReviewId) + FROM '.$object->TableName.' + WHERE ItemId='.$product_info['ParentId']; + $review_qty = $this->Conn->GetOne($sql); + $product_object->SetDBField('CachedReviewsQty', $review_qty); + $product_object->Update(); + $expire = adodb_mktime() + $this->Application->ConfigValue('product_ReviewDelay_Value') * $this->Application->ConfigValue('product_ReviewDelay_Interval'); + $sql = ' INSERT INTO '.TABLE_PREFIX.'SpamControl + (ItemResourceId, IPaddress, PortalUserId, DataType, Expire) + VALUES ('.$product_info['ParentId'].', + "'.$_SERVER['REMOTE_ADDR'].'", + '.$user_id.', + "Review", + '.$expire.')'; + $this->Conn->Query($sql); + + $event->redirect_params = Array('pass' => 'all,p'); + $event->redirect = $this->Application->GetVar('success_template'); + } + } + else + { + $event->status == erFAIL; + $event->redirect=false; + $object->FieldErrors['ReviewText']['pseudo'] = 'too_frequent'; + $object->ErrorMsgs['too_frequent'] = $this->Application->Phrase('lu_ferror_review_duplicate'); + } + } + } + +?> \ No newline at end of file Index: trunk/kernel/units/images/images.php =================================================================== diff -u -N --- trunk/kernel/units/images/images.php (revision 0) +++ trunk/kernel/units/images/images.php (revision 4303) @@ -0,0 +1,23 @@ +Load($id); + $local_path = FULL_PATH.$this->GetDBField('LocalPath'); + $thumb_path = FULL_PATH.$this->GetDBField('ThumbPath'); + if(file_exists($local_path)) + { + unlink($local_path); + } + if(file_exists($thumb_path)) + { + unlink($thumb_path); + } + return parent::Delete($id); + } + +} + +?> \ No newline at end of file Index: trunk/core/units/reviews/reviews_event_handler.php =================================================================== diff -u -N --- trunk/core/units/reviews/reviews_event_handler.php (revision 0) +++ trunk/core/units/reviews/reviews_event_handler.php (revision 4303) @@ -0,0 +1,142 @@ +getObject(); + switch ($event->Special) + { + case 'showall': + $object->clearFilters(); + break; + + case 'products': + $object->removeFilter('parent_filter'); // this is important + $object->addFilter('product_reviews', '%1$s.ItemId = pr.ResourceId'); + // $object->addFilter('active', '%1$s.Status = 1'); + + /*$this->Application->setUnitOption('p', 'AutoLoad', true); + $product =& $this->Application->recallObject('p'); + $object->addFilter('current_product', 'pr.ResourceId = '.$product->GetDBField('ResourceId'));*/ + break; + + case 'product': + $object->clearFilters(); + $object->addFilter('product_reviews', '%1$s.ItemId = pr.ResourceId'); + $object->addFilter('active', '%1$s.Status = 1'); + $this->Application->setUnitOption('p', 'AutoLoad', true); + $product =& $this->Application->recallObject('p'); + $object->addFilter('current_product', 'pr.ResourceId = '.$product->GetDBField('ResourceId')); + + break; + } + + if($event->getEventParam('type') == 'current_user') + { + $user_id = $this->Application->GetVar('u_id') ? $this->Application->GetVar('u_id') : -2; + $ip = $_SERVER['REMOTE_ADDR']; + $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $event->getObject(); + $product_info = $object->getLinkedInfo(); + $object->addFilter('current_item', '%1$s.ItemId = '.$product_info['ParentId']); + $object->addFilter('current_user', '%1$s.CreatedById = '.$user_id); + $object->addFilter('current_ip', '%1$s.IPAddress = "'.$ip.'"'); + + } + } + + /** + * Adds review from front in case if user is logged in + * + * @param kEvent $event + */ + function OnAddReview(&$event) + { + $user_id = ($this->Application->GetVar('u_id') == 0) ? -2 : $this->Application->GetVar('u_id'); + $event->redirect_params = Array('pass' => 'all,p'); + + $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $event->getObject(); + $item_info = $this->Application->GetVar('rev_product'); + $product_info = $object->getLinkedInfo(); + + $sql = ' SELECT * FROM '.TABLE_PREFIX.'SpamControl + WHERE ItemResourceId='.$product_info['ParentId'].' + AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'" + AND PortalUserId='.$user_id.' + AND DataType="Review"'; + $res = $this->Conn->GetRow($sql); + + if( $res && $res['Expire'] < adodb_mktime() ) + { + $sql = ' DELETE FROM '.TABLE_PREFIX.'SpamControl + WHERE ItemResourceId='.$product_info['ParentId'].' + AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'" + AND PortalUserId='.$user_id.' + AND DataType="Review"'; + $this->Conn->Query($sql); + unset($res); + } + + if(!$res) + { + $object->SetFieldsFromHash( array_shift($item_info) ); + $object->SetDBField('CreatedById', $user_id); + $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']); + $object->SetDBField('CreatedOn', adodb_mktime()); + + if( $this->Application->CheckPermission('PRODUCT.REVIEW.PENDING') ) + { + $object->SetDBField('Status', 2); + } + elseif( $this->Application->CheckPermission('PRODUCT.REVIEW') ) + { + $object->SetDBField('Status', 1); + } + + $object->SetDBField('ItemId', $product_info['ParentId']); + + $event->CallSubEvent('OnCreate'); + + if($event->status == erSUCCESS) + { + $product_object =& $this->Application->recallObject('p'); + $sql = ' SELECT COUNT(ReviewId) + FROM '.$object->TableName.' + WHERE ItemId='.$product_info['ParentId']; + $review_qty = $this->Conn->GetOne($sql); + $product_object->SetDBField('CachedReviewsQty', $review_qty); + $product_object->Update(); + $expire = adodb_mktime() + $this->Application->ConfigValue('product_ReviewDelay_Value') * $this->Application->ConfigValue('product_ReviewDelay_Interval'); + $sql = ' INSERT INTO '.TABLE_PREFIX.'SpamControl + (ItemResourceId, IPaddress, PortalUserId, DataType, Expire) + VALUES ('.$product_info['ParentId'].', + "'.$_SERVER['REMOTE_ADDR'].'", + '.$user_id.', + "Review", + '.$expire.')'; + $this->Conn->Query($sql); + + $event->redirect_params = Array('pass' => 'all,p'); + $event->redirect = $this->Application->GetVar('success_template'); + } + } + else + { + $event->status == erFAIL; + $event->redirect=false; + $object->FieldErrors['ReviewText']['pseudo'] = 'too_frequent'; + $object->ErrorMsgs['too_frequent'] = $this->Application->Phrase('lu_ferror_review_duplicate'); + } + } + } + +?> \ No newline at end of file Index: trunk/core/units/images/images.php =================================================================== diff -u -N --- trunk/core/units/images/images.php (revision 0) +++ trunk/core/units/images/images.php (revision 4303) @@ -0,0 +1,23 @@ +Load($id); + $local_path = FULL_PATH.$this->GetDBField('LocalPath'); + $thumb_path = FULL_PATH.$this->GetDBField('ThumbPath'); + if(file_exists($local_path)) + { + unlink($local_path); + } + if(file_exists($thumb_path)) + { + unlink($thumb_path); + } + return parent::Delete($id); + } + +} + +?> \ No newline at end of file Index: trunk/core/units/reviews/reviews_config.php =================================================================== diff -u -N --- trunk/core/units/reviews/reviews_config.php (revision 0) +++ trunk/core/units/reviews/reviews_config.php (revision 4303) @@ -0,0 +1,131 @@ + 'rev', + + 'Clones' => Array( + + 'l-rev' => Array('ParentPrefix' => 'l'), + 'n-rev' => Array('ParentPrefix' => 'n'), + 'bb-rev'=> Array('ParentPrefix' => 'bb'), + 'p-rev' => Array('ParentPrefix' => 'p'), + ), + + 'ItemClass' => Array('class'=>'kDBItem','file'=>'','build_event'=>'OnItemBuild'), + 'ListClass' => Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'), + 'EventHandlerClass' => Array('class'=>'ReviewsEventHandler','file'=>'reviews_event_handler.php','build_event'=>'OnBuild'), + 'TagProcessorClass' => Array('class'=>'ReviewsTagProcessor','file'=>'reviews_tag_processor.php','build_event'=>'OnBuild'), + 'AutoLoad' => true, + + 'QueryString' => Array( + 1 => 'id', + 2 => 'page', + 3 => 'event', + ), + + + 'ParentPrefix' => 'p', // replace all usage of rev to "p-rev" and then remove this param from here and Prefix too + + 'IDField' => 'ReviewId', + 'StatusField' => Array('Status'), // field, that is affected by Approve/Decline events + 'TableName' => TABLE_PREFIX.'ItemReview', + 'ParentTableKey' => 'ResourceId', // linked field in master table + 'ForeignKey' => 'ItemId', // linked field in subtable + + 'AutoDelete' => true, + 'AutoClone' => true, + + 'TitlePresets' => Array( + 'reviews_edit' => Array('format' => "!la_title_Editing_Review!"), + ), + 'FilterMenu' => Array( + 'Groups' => Array( + Array('mode' => 'AND', 'filters' => Array('show_active','show_pending','show_disabled'), 'type' => WHERE_FILTER), + ), + 'Filters' => Array( + 'show_active' => Array('label' =>'la_Active', 'on_sql' => '', 'off_sql' => '%1$s.Status != 1' ), + 'show_pending' => Array('label' => 'la_Pending', 'on_sql' => '', 'off_sql' => '%1$s.Status != 2' ), + 'show_disabled' => Array('label' => 'la_Disabled', 'on_sql' => '', 'off_sql' => '%1$s.Status != 0' ), + ) + ), + + 'CalculatedFields' => Array( + '' => Array( + 'ReviewedBy' => 'IF( ISNULL(pu.Login), IF (%1$s.CreatedById = -1, \'root\', IF (%1$s.CreatedById = -2, \'Guest\', \'n/a\')), pu.Login )', + ), + 'products' => Array( + 'ReviewedBy' => 'IF( ISNULL(pu.Login), IF (%1$s.CreatedById = -1, \'root\', IF (%1$s.CreatedById = -2, \'Guest\', \'n/a\')), pu.Login )', + 'ItemName' => 'pr.l1_Name', + 'ProductId' => 'pr.ProductId', + ), + 'product' => Array( + 'ReviewedBy' => 'IF( ISNULL(pu.Login), IF (%1$s.CreatedById = -1, \'root\', IF (%1$s.CreatedById = -2, \'Guest\', \'n/a\')), pu.Login )', + 'ItemName' => 'pr.l1_Name', + 'ProductId' => 'pr.ProductId', + ), + + ), + + // key - special, value - list select sql + 'ListSQLs' => Array( ''=>'SELECT %1$s.* %2$s FROM %1$s + LEFT JOIN '.TABLE_PREFIX.'PortalUser pu ON pu.PortalUserId = %1$s.CreatedById', + + 'products' => ' SELECT %1$s.* %2$s + FROM %1$s, '.TABLE_PREFIX.'Products pr + LEFT JOIN '.TABLE_PREFIX.'PortalUser pu ON pu.PortalUserId = %1$s.CreatedById', + + 'product' => ' SELECT %1$s.* %2$s + FROM %1$s, '.TABLE_PREFIX.'Products pr + LEFT JOIN '.TABLE_PREFIX.'PortalUser pu ON pu.PortalUserId = %1$s.CreatedById', + ), + + 'ItemSQLs' => Array( ''=> 'SELECT * FROM %s'), + + 'ListSortings' => Array( + '' => Array( + 'ForcedSorting' => Array('Priority' => 'desc'), + 'Sorting' => Array('CreatedOn' => 'desc'), + ) + ), + + 'Fields' => Array( + 'ReviewId' => Array('type'=>'int'), + 'CreatedOn' => Array('formatter'=>'kDateFormatter','not_null'=>1,'default'=>'#NOW#'), + 'ReviewText' => Array('type'=>'string','required'=>1,'not_null'=>1,'default'=>''), + 'IPAddress' => Array('type'=>'string','max_value_inc'=>15,'not_null'=>1,'default'=>''), + 'ItemId' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'CreatedById' => Array('formatter'=>'kLEFTFormatter','options'=>Array(-1=>'root',-2=>'Guest'),'left_sql'=>'SELECT %s FROM '.TABLE_PREFIX.'PortalUser WHERE `%s` = \'%s\'','left_key_field'=>'PortalUserId','left_title_field'=>'Login','required'=>1,'not_null'=>1,'default'=>-1), + 'ItemType' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'Priority' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'Status' => Array('formatter'=>'kOptionsFormatter', 'use_phrases' => 1, 'options'=>Array(1=>'la_Active',2=>'la_Pending',0=>'la_Disabled'),'not_null'=>1,'default'=>0 ), + 'TextFormat' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'Module' => Array('type'=>'string','not_null'=>1,'default'=>''), + ), + 'VirtualFields' => Array( + 'ReviewedBy' => Array(), + ), + + 'Grids' => Array( + 'Default' => Array( 'Icons' => Array('default'=>'icon16_custom.gif',1=>'icon16_review.gif',2=>'icon16_review_pending.gif',0=>'icon16_review_disabled.gif'), + 'Fields' => Array( + 'ReviewText' => Array( 'title'=>'la_col_ReviewText', 'data_block' => 'reviewtext_checkbox_td'), + 'ReviewedBy' => Array( 'title'=>'la_col_ReviewedBy' ), + 'CreatedOn_formatted' => Array( 'title'=>'la_col_CreatedOn', 'sort_field' => 'CreatedOn' ), + 'Status' => Array( 'title'=>'la_col_Status' ), + ), + + ), + + 'ReviewsSection' => Array( 'Icons' => Array('default'=>'icon16_custom.gif',1=>'icon16_review.gif',2=>'icon16_review_pending.gif',0=>'icon16_review_disabled.gif'), + 'Fields' => Array( + 'ReviewText' => Array( 'title'=>'la_col_ReviewText', 'data_block' => 'grid_checkbox_namelink_td'), + 'ReviewedBy' => Array( 'title'=>'la_col_ReviewedBy' ), + 'CreatedOn_formatted' => Array( 'title'=>'la_col_CreatedOn', 'sort_field' => 'CreatedOn' ), + 'Status' => Array( 'title'=>'la_col_Status' ), + ), + + ), + ), + ); + +?> \ No newline at end of file Index: trunk/kernel/units/reviews/reviews_config.php =================================================================== diff -u -N --- trunk/kernel/units/reviews/reviews_config.php (revision 0) +++ trunk/kernel/units/reviews/reviews_config.php (revision 4303) @@ -0,0 +1,131 @@ + 'rev', + + 'Clones' => Array( + + 'l-rev' => Array('ParentPrefix' => 'l'), + 'n-rev' => Array('ParentPrefix' => 'n'), + 'bb-rev'=> Array('ParentPrefix' => 'bb'), + 'p-rev' => Array('ParentPrefix' => 'p'), + ), + + 'ItemClass' => Array('class'=>'kDBItem','file'=>'','build_event'=>'OnItemBuild'), + 'ListClass' => Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'), + 'EventHandlerClass' => Array('class'=>'ReviewsEventHandler','file'=>'reviews_event_handler.php','build_event'=>'OnBuild'), + 'TagProcessorClass' => Array('class'=>'ReviewsTagProcessor','file'=>'reviews_tag_processor.php','build_event'=>'OnBuild'), + 'AutoLoad' => true, + + 'QueryString' => Array( + 1 => 'id', + 2 => 'page', + 3 => 'event', + ), + + + 'ParentPrefix' => 'p', // replace all usage of rev to "p-rev" and then remove this param from here and Prefix too + + 'IDField' => 'ReviewId', + 'StatusField' => Array('Status'), // field, that is affected by Approve/Decline events + 'TableName' => TABLE_PREFIX.'ItemReview', + 'ParentTableKey' => 'ResourceId', // linked field in master table + 'ForeignKey' => 'ItemId', // linked field in subtable + + 'AutoDelete' => true, + 'AutoClone' => true, + + 'TitlePresets' => Array( + 'reviews_edit' => Array('format' => "!la_title_Editing_Review!"), + ), + 'FilterMenu' => Array( + 'Groups' => Array( + Array('mode' => 'AND', 'filters' => Array('show_active','show_pending','show_disabled'), 'type' => WHERE_FILTER), + ), + 'Filters' => Array( + 'show_active' => Array('label' =>'la_Active', 'on_sql' => '', 'off_sql' => '%1$s.Status != 1' ), + 'show_pending' => Array('label' => 'la_Pending', 'on_sql' => '', 'off_sql' => '%1$s.Status != 2' ), + 'show_disabled' => Array('label' => 'la_Disabled', 'on_sql' => '', 'off_sql' => '%1$s.Status != 0' ), + ) + ), + + 'CalculatedFields' => Array( + '' => Array( + 'ReviewedBy' => 'IF( ISNULL(pu.Login), IF (%1$s.CreatedById = -1, \'root\', IF (%1$s.CreatedById = -2, \'Guest\', \'n/a\')), pu.Login )', + ), + 'products' => Array( + 'ReviewedBy' => 'IF( ISNULL(pu.Login), IF (%1$s.CreatedById = -1, \'root\', IF (%1$s.CreatedById = -2, \'Guest\', \'n/a\')), pu.Login )', + 'ItemName' => 'pr.l1_Name', + 'ProductId' => 'pr.ProductId', + ), + 'product' => Array( + 'ReviewedBy' => 'IF( ISNULL(pu.Login), IF (%1$s.CreatedById = -1, \'root\', IF (%1$s.CreatedById = -2, \'Guest\', \'n/a\')), pu.Login )', + 'ItemName' => 'pr.l1_Name', + 'ProductId' => 'pr.ProductId', + ), + + ), + + // key - special, value - list select sql + 'ListSQLs' => Array( ''=>'SELECT %1$s.* %2$s FROM %1$s + LEFT JOIN '.TABLE_PREFIX.'PortalUser pu ON pu.PortalUserId = %1$s.CreatedById', + + 'products' => ' SELECT %1$s.* %2$s + FROM %1$s, '.TABLE_PREFIX.'Products pr + LEFT JOIN '.TABLE_PREFIX.'PortalUser pu ON pu.PortalUserId = %1$s.CreatedById', + + 'product' => ' SELECT %1$s.* %2$s + FROM %1$s, '.TABLE_PREFIX.'Products pr + LEFT JOIN '.TABLE_PREFIX.'PortalUser pu ON pu.PortalUserId = %1$s.CreatedById', + ), + + 'ItemSQLs' => Array( ''=> 'SELECT * FROM %s'), + + 'ListSortings' => Array( + '' => Array( + 'ForcedSorting' => Array('Priority' => 'desc'), + 'Sorting' => Array('CreatedOn' => 'desc'), + ) + ), + + 'Fields' => Array( + 'ReviewId' => Array('type'=>'int'), + 'CreatedOn' => Array('formatter'=>'kDateFormatter','not_null'=>1,'default'=>'#NOW#'), + 'ReviewText' => Array('type'=>'string','required'=>1,'not_null'=>1,'default'=>''), + 'IPAddress' => Array('type'=>'string','max_value_inc'=>15,'not_null'=>1,'default'=>''), + 'ItemId' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'CreatedById' => Array('formatter'=>'kLEFTFormatter','options'=>Array(-1=>'root',-2=>'Guest'),'left_sql'=>'SELECT %s FROM '.TABLE_PREFIX.'PortalUser WHERE `%s` = \'%s\'','left_key_field'=>'PortalUserId','left_title_field'=>'Login','required'=>1,'not_null'=>1,'default'=>-1), + 'ItemType' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'Priority' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'Status' => Array('formatter'=>'kOptionsFormatter', 'use_phrases' => 1, 'options'=>Array(1=>'la_Active',2=>'la_Pending',0=>'la_Disabled'),'not_null'=>1,'default'=>0 ), + 'TextFormat' => Array('type'=>'int','not_null'=>1,'default'=>0), + 'Module' => Array('type'=>'string','not_null'=>1,'default'=>''), + ), + 'VirtualFields' => Array( + 'ReviewedBy' => Array(), + ), + + 'Grids' => Array( + 'Default' => Array( 'Icons' => Array('default'=>'icon16_custom.gif',1=>'icon16_review.gif',2=>'icon16_review_pending.gif',0=>'icon16_review_disabled.gif'), + 'Fields' => Array( + 'ReviewText' => Array( 'title'=>'la_col_ReviewText', 'data_block' => 'reviewtext_checkbox_td'), + 'ReviewedBy' => Array( 'title'=>'la_col_ReviewedBy' ), + 'CreatedOn_formatted' => Array( 'title'=>'la_col_CreatedOn', 'sort_field' => 'CreatedOn' ), + 'Status' => Array( 'title'=>'la_col_Status' ), + ), + + ), + + 'ReviewsSection' => Array( 'Icons' => Array('default'=>'icon16_custom.gif',1=>'icon16_review.gif',2=>'icon16_review_pending.gif',0=>'icon16_review_disabled.gif'), + 'Fields' => Array( + 'ReviewText' => Array( 'title'=>'la_col_ReviewText', 'data_block' => 'grid_checkbox_namelink_td'), + 'ReviewedBy' => Array( 'title'=>'la_col_ReviewedBy' ), + 'CreatedOn_formatted' => Array( 'title'=>'la_col_CreatedOn', 'sort_field' => 'CreatedOn' ), + 'Status' => Array( 'title'=>'la_col_Status' ), + ), + + ), + ), + ); + +?> \ No newline at end of file Index: trunk/kernel/units/relationship/relationship_event_handler.php =================================================================== diff -u -N --- trunk/kernel/units/relationship/relationship_event_handler.php (revision 0) +++ trunk/kernel/units/relationship/relationship_event_handler.php (revision 4303) @@ -0,0 +1,176 @@ +Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $event->getObject(); + + $table_info = $object->getLinkedInfo(); + $main_item_type = $this->Application->getUnitOption($table_info['ParentPrefix'],'ItemType'); + + $target['id'] = $this->Application->GetVar('TargetId'); + $target['type'] = $this->Application->GetVar('TargetType'); + + + $object->SetDBField($table_info['ForeignKey'], $table_info['ParentId']); + $object->SetDBField('SourceType', $main_item_type); + $object->SetDBField('TargetId', $target['id']); + $object->SetDBField('TargetType', $target['type']); + + // 1. get item info used in relation + $configs = $this->extractModulesInfo(); + foreach($configs as $prefix => $config_data) + { + if($config_data['ItemType'] == $target['type']) break; + } + + $db =& $this->Application->GetADODBConnection(); + $item['name'] = $db->GetOne('SELECT '.$config_data['TitleField'].' FROM '.$config_data['TableName'].' WHERE ResourceId = '.$target['id']); + $item['type'] = $this->Application->Phrase($config_data['TitlePhrase']); + $object->SetDBField('ItemName', $item['name']); + $object->SetDBField('ItemType', $item['type']); + + $object->setID(0); + + $event->redirect = false; + + // 2. substitute opener + $opener_stack = $this->Application->RecallVar('opener_stack'); + $opener_stack = $opener_stack ? unserialize($opener_stack) : Array(); + array_pop($opener_stack); + + $new_level = 'index4.php|'.ltrim($this->Application->BuildEnv('in-commerce/products/products_relations',Array('m_opener'=>'u'),'all'),ENV_VAR_NAME.'='); + array_push($opener_stack,$new_level); + $this->Application->StoreVar('opener_stack',serialize($opener_stack)); + + $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnCreate'); + } + + /** + * Creates needed sql query to load list, + * if no query is defined in config for + * special requested, then use default + * query + * + * @param kEvent $event + * @access protected + */ + function ListPrepareQuery(&$event) + { + return $this->BaseQuery($event,'ListSQLs'); + } + + /** + * Creates needed sql query to load item, + * if no query is defined in config for + * special requested, then use default + * query + * + * @param kEvent $event + * @access protected + */ + function ItemPrepareQuery(&$event) + { + return $this->BaseQuery($event,'ItemSQLs'); + } + + + /** + * Get item name & type based on relation type & modules installed + * + * @param kEvent $event + * @param string $sql_field + */ + function BaseQuery(&$event, $sql_field) + { + $sqls = $this->Application->getUnitOption($event->Prefix,$sql_field); + $sql = isset($sqls[$event->Special]) ? $sqls[$event->Special] : $sqls['']; + + $configs = $this->extractModulesInfo(); + + // 2. build sql based on information queried + $sql_templates['ItemName'] = 'IFNULL(%s.%s,\' \')'; + $sql_templates['TableJoin'] = 'LEFT JOIN %1$s ON %1$s.ResourceId = rel.TargetId'; + $sql_templates['TargetName'] = 'IF(rel.TargetType = %s, \'%s\', %s)'; + + $sql_parts = Array(); + $sql_parts['TargetName'] = "''"; + foreach($configs as $prefix => $config_data) + { + $sql_parts['ItemName'][] = sprintf($sql_templates['ItemName'], $config_data['TableName'], $config_data['TitleField']); + $sql_parts['TableJoin'][] = sprintf($sql_templates['TableJoin'], $config_data['TableName']); + + $sql_parts['TargetName'] = sprintf( $sql_templates['TargetName'], + $config_data['ItemType'], + '!'.$config_data['TitlePhrase'].'!', + $sql_parts['TargetName']); + $sql_parts['TargetName'] = str_replace('rel','%1$s',$sql_parts['TargetName']); + } + + $object =& $event->getObject(); + + $vars = Array('#ITEM_NAMES#', '#ITEM_TYPES#'); + $replacements = Array( implode(', ',$sql_parts['ItemName']), $sql_parts['TargetName'] ); + + $calculated_fields =& $object->getProperty('CalculatedFields'); + foreach($calculated_fields as $field_name => $field_expression) + { + $calculated_fields[$field_name] = str_replace($vars,$replacements,$field_expression); + } + + $object->setProperty('CalculatedFields', $calculated_fields); + + $sql = str_replace('#ITEM_JOIN#', implode(' ',$sql_parts['TableJoin']), $sql); + $sql = str_replace('rel.','%1$s.',$sql); + + return $sql; + } + + /** + * Get configs from modules installed + * + * @return Array + * @access private + */ + function extractModulesInfo() + { + // 1. get installed modules & their config info + $db =& $this->Application->GetADODBConnection(); + $prefixes = $db->GetCol('SELECT Var FROM '.TABLE_PREFIX.'Modules'); + $configs = Array(); + foreach($prefixes as $prefix) + { + $configs[$prefix] = $this->Application->getUnitOptions($prefix); + if($configs[$prefix] === false) unset($configs[$prefix]); + } + return $configs; + } + + + /** + * Deletes relations to hooked item from other items + * + * @param kEvent $event + */ + function OnDeleteForeignRelations(&$event) + { + $main_object =& $event->MasterEvent->getObject(); + $resource_id = $main_object->GetDBField('ResourceId'); + + $table = $this->Application->getUnitOption($event->Prefix,'TableName'); + $sql = 'DELETE FROM '.$table.' WHERE TargetId = '.$resource_id; + $this->Conn->Query($sql); + } + + + } + + +?> \ No newline at end of file Index: trunk/kernel/units/reviews/reviews_tag_processor.php =================================================================== diff -u -N --- trunk/kernel/units/reviews/reviews_tag_processor.php (revision 0) +++ trunk/kernel/units/reviews/reviews_tag_processor.php (revision 4303) @@ -0,0 +1,102 @@ +Application->getUnitOption($item_prefix,'IDField'); + + $object =& $this->Application->recallObject($this->getPrefixSpecial(),$this->Prefix, $params); + $item_id = $object->GetDBField($id_field); + + return $this->Application->HREF($params['edit_template'],'', Array( + 'm_opener'=>'d', + $item_prefix.'_event'=>'OnEdit', + $item_prefix.'_id'=>$item_id, + 'pass'=>'all,'.$item_prefix + ),'index4.php' ); + } + + /** + * Get's reuested field value + * + * @param Array $params + * @return string + * @access public + */ + function Field($params) + { + $field = $this->SelectParam($params, 'name,field'); + $object =& $this->Application->recallObject($this->getPrefixSpecial(),$this->Prefix, $params); + + if($field == 'ReviewText') + { + if( $object->GetDBField('TextFormat') == 1 ) + { + $params['no_special'] = 'no_special'; + } + else + { + unset($params['no_special']); + } + } + + return parent::Field($params); + + } + + function AlreadyReviewed($params) + { + $user_id = ($this->Application->GetVar('u_id') == 0) ? -2 : $this->Application->GetVar('u_id'); + $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $this->Application->recallObject($this->getPrefixSpecial()); + $product_info = $object->getLinkedInfo(); + + $sql = ' SELECT * FROM '.TABLE_PREFIX.'SpamControl + WHERE ItemResourceId='.$product_info['ParentId'].' + AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'" + AND PortalUserId='.$user_id.' + AND DataType="Review"'; + $res = $this->Conn->GetRow($sql); + if($res['Expire'] > adodb_mktime()) + { + $ret = 1; + } + else + { + $sql = 'DELETE FROM '.TABLE_PREFIX.'SpamControl + WHERE ItemResourceId='.$product_info['ParentId'].' + AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'" + AND PortalUserId='.$user_id.' + AND DataType="Review"'; + $this->Conn->Query($sql); + $ret = 0; + } + return $ret; + } + + function HasError($params) + { + $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); + if(method_exists($object, 'GetErrorMsg')) + { + return parent::HasError($params); + } + else + { + return 0; + } + } +} + + +?> \ No newline at end of file Index: trunk/core/units/relationship/relationship_event_handler.php =================================================================== diff -u -N --- trunk/core/units/relationship/relationship_event_handler.php (revision 0) +++ trunk/core/units/relationship/relationship_event_handler.php (revision 4303) @@ -0,0 +1,176 @@ +Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $event->getObject(); + + $table_info = $object->getLinkedInfo(); + $main_item_type = $this->Application->getUnitOption($table_info['ParentPrefix'],'ItemType'); + + $target['id'] = $this->Application->GetVar('TargetId'); + $target['type'] = $this->Application->GetVar('TargetType'); + + + $object->SetDBField($table_info['ForeignKey'], $table_info['ParentId']); + $object->SetDBField('SourceType', $main_item_type); + $object->SetDBField('TargetId', $target['id']); + $object->SetDBField('TargetType', $target['type']); + + // 1. get item info used in relation + $configs = $this->extractModulesInfo(); + foreach($configs as $prefix => $config_data) + { + if($config_data['ItemType'] == $target['type']) break; + } + + $db =& $this->Application->GetADODBConnection(); + $item['name'] = $db->GetOne('SELECT '.$config_data['TitleField'].' FROM '.$config_data['TableName'].' WHERE ResourceId = '.$target['id']); + $item['type'] = $this->Application->Phrase($config_data['TitlePhrase']); + $object->SetDBField('ItemName', $item['name']); + $object->SetDBField('ItemType', $item['type']); + + $object->setID(0); + + $event->redirect = false; + + // 2. substitute opener + $opener_stack = $this->Application->RecallVar('opener_stack'); + $opener_stack = $opener_stack ? unserialize($opener_stack) : Array(); + array_pop($opener_stack); + + $new_level = 'index4.php|'.ltrim($this->Application->BuildEnv('in-commerce/products/products_relations',Array('m_opener'=>'u'),'all'),ENV_VAR_NAME.'='); + array_push($opener_stack,$new_level); + $this->Application->StoreVar('opener_stack',serialize($opener_stack)); + + $this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnCreate'); + } + + /** + * Creates needed sql query to load list, + * if no query is defined in config for + * special requested, then use default + * query + * + * @param kEvent $event + * @access protected + */ + function ListPrepareQuery(&$event) + { + return $this->BaseQuery($event,'ListSQLs'); + } + + /** + * Creates needed sql query to load item, + * if no query is defined in config for + * special requested, then use default + * query + * + * @param kEvent $event + * @access protected + */ + function ItemPrepareQuery(&$event) + { + return $this->BaseQuery($event,'ItemSQLs'); + } + + + /** + * Get item name & type based on relation type & modules installed + * + * @param kEvent $event + * @param string $sql_field + */ + function BaseQuery(&$event, $sql_field) + { + $sqls = $this->Application->getUnitOption($event->Prefix,$sql_field); + $sql = isset($sqls[$event->Special]) ? $sqls[$event->Special] : $sqls['']; + + $configs = $this->extractModulesInfo(); + + // 2. build sql based on information queried + $sql_templates['ItemName'] = 'IFNULL(%s.%s,\' \')'; + $sql_templates['TableJoin'] = 'LEFT JOIN %1$s ON %1$s.ResourceId = rel.TargetId'; + $sql_templates['TargetName'] = 'IF(rel.TargetType = %s, \'%s\', %s)'; + + $sql_parts = Array(); + $sql_parts['TargetName'] = "''"; + foreach($configs as $prefix => $config_data) + { + $sql_parts['ItemName'][] = sprintf($sql_templates['ItemName'], $config_data['TableName'], $config_data['TitleField']); + $sql_parts['TableJoin'][] = sprintf($sql_templates['TableJoin'], $config_data['TableName']); + + $sql_parts['TargetName'] = sprintf( $sql_templates['TargetName'], + $config_data['ItemType'], + '!'.$config_data['TitlePhrase'].'!', + $sql_parts['TargetName']); + $sql_parts['TargetName'] = str_replace('rel','%1$s',$sql_parts['TargetName']); + } + + $object =& $event->getObject(); + + $vars = Array('#ITEM_NAMES#', '#ITEM_TYPES#'); + $replacements = Array( implode(', ',$sql_parts['ItemName']), $sql_parts['TargetName'] ); + + $calculated_fields =& $object->getProperty('CalculatedFields'); + foreach($calculated_fields as $field_name => $field_expression) + { + $calculated_fields[$field_name] = str_replace($vars,$replacements,$field_expression); + } + + $object->setProperty('CalculatedFields', $calculated_fields); + + $sql = str_replace('#ITEM_JOIN#', implode(' ',$sql_parts['TableJoin']), $sql); + $sql = str_replace('rel.','%1$s.',$sql); + + return $sql; + } + + /** + * Get configs from modules installed + * + * @return Array + * @access private + */ + function extractModulesInfo() + { + // 1. get installed modules & their config info + $db =& $this->Application->GetADODBConnection(); + $prefixes = $db->GetCol('SELECT Var FROM '.TABLE_PREFIX.'Modules'); + $configs = Array(); + foreach($prefixes as $prefix) + { + $configs[$prefix] = $this->Application->getUnitOptions($prefix); + if($configs[$prefix] === false) unset($configs[$prefix]); + } + return $configs; + } + + + /** + * Deletes relations to hooked item from other items + * + * @param kEvent $event + */ + function OnDeleteForeignRelations(&$event) + { + $main_object =& $event->MasterEvent->getObject(); + $resource_id = $main_object->GetDBField('ResourceId'); + + $table = $this->Application->getUnitOption($event->Prefix,'TableName'); + $sql = 'DELETE FROM '.$table.' WHERE TargetId = '.$resource_id; + $this->Conn->Query($sql); + } + + + } + + +?> \ No newline at end of file Index: trunk/core/units/reviews/reviews_tag_processor.php =================================================================== diff -u -N --- trunk/core/units/reviews/reviews_tag_processor.php (revision 0) +++ trunk/core/units/reviews/reviews_tag_processor.php (revision 4303) @@ -0,0 +1,102 @@ +Application->getUnitOption($item_prefix,'IDField'); + + $object =& $this->Application->recallObject($this->getPrefixSpecial(),$this->Prefix, $params); + $item_id = $object->GetDBField($id_field); + + return $this->Application->HREF($params['edit_template'],'', Array( + 'm_opener'=>'d', + $item_prefix.'_event'=>'OnEdit', + $item_prefix.'_id'=>$item_id, + 'pass'=>'all,'.$item_prefix + ),'index4.php' ); + } + + /** + * Get's reuested field value + * + * @param Array $params + * @return string + * @access public + */ + function Field($params) + { + $field = $this->SelectParam($params, 'name,field'); + $object =& $this->Application->recallObject($this->getPrefixSpecial(),$this->Prefix, $params); + + if($field == 'ReviewText') + { + if( $object->GetDBField('TextFormat') == 1 ) + { + $params['no_special'] = 'no_special'; + } + else + { + unset($params['no_special']); + } + } + + return parent::Field($params); + + } + + function AlreadyReviewed($params) + { + $user_id = ($this->Application->GetVar('u_id') == 0) ? -2 : $this->Application->GetVar('u_id'); + $this->Application->setUnitOption($event->Prefix,'AutoLoad',false); + $object =& $this->Application->recallObject($this->getPrefixSpecial()); + $product_info = $object->getLinkedInfo(); + + $sql = ' SELECT * FROM '.TABLE_PREFIX.'SpamControl + WHERE ItemResourceId='.$product_info['ParentId'].' + AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'" + AND PortalUserId='.$user_id.' + AND DataType="Review"'; + $res = $this->Conn->GetRow($sql); + if($res['Expire'] > adodb_mktime()) + { + $ret = 1; + } + else + { + $sql = 'DELETE FROM '.TABLE_PREFIX.'SpamControl + WHERE ItemResourceId='.$product_info['ParentId'].' + AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'" + AND PortalUserId='.$user_id.' + AND DataType="Review"'; + $this->Conn->Query($sql); + $ret = 0; + } + return $ret; + } + + function HasError($params) + { + $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); + if(method_exists($object, 'GetErrorMsg')) + { + return parent::HasError($params); + } + else + { + return 0; + } + } +} + + +?> \ No newline at end of file Index: trunk/core/kernel/processors/main_processor.php =================================================================== diff -u -N -r4300 -r4303 --- trunk/core/kernel/processors/main_processor.php (.../main_processor.php) (revision 4300) +++ trunk/core/kernel/processors/main_processor.php (.../main_processor.php) (revision 4303) @@ -797,7 +797,7 @@ function ConstOn($params) { $name = $this->SelectParam($params,'name,const'); - return $this->Application->isDebugMode() && dbg_ConstOn($name); + return ConstOn($name); } function SetDefaultCategory($params) Index: trunk/core/units/images/image_event_handler.php =================================================================== diff -u -N --- trunk/core/units/images/image_event_handler.php (revision 0) +++ trunk/core/units/images/image_event_handler.php (revision 4303) @@ -0,0 +1,336 @@ +'ImageAction', + 'OnBeforeDeleteFromLive'=>'ImageAction', + 'OnBeforeCopyToLive'=>'ImageAction', + 'OnBeforeItemDelete'=>'ImageAction', + 'OnAfterClone'=>'ImageAction', + ); + + $this->eventMethods = array_merge($this->eventMethods, $image_events); + } + + function customProcessing(&$event, $type) + { + $object =& $event->GetObject(); + switch ($type) + { + case 'before' : + if ($object->GetDBField('LocalImage')) + { + $object->SetDBField('Url', ''); + } + else + { + $object->SetDBField('LocalPath', ''); + } + + if ($object->GetDBField('LocalThumb')) + { + $object->SetDBField('ThumbUrl', ''); + } + else + { + $object->SetDBField('ThumbPath', ''); + } + + if ($object->GetDBField('SameImages')) + { + $object->SetDBField('LocalImage', 1); + $object->SetDBField('LocalPath', ''); + $object->SetDBField('Url', ''); + } + break; + case 'after' : + if ($object->GetDBField('DefaultImg') ) + { + $sql = 'UPDATE '.$object->TableName.' SET DefaultImg=0 WHERE ResourceId='. + $object->GetDBField('ResourceId').' AND ImageId<>'. + $object->GetId(); + $res = $this->Conn->Query($sql); + } + break; + default: + } + } + + function ImageAction(&$event) + { + $id = $event->getEventParam('id'); + $object =& $this->Application->recallObject($event->Prefix.'.-item', $event->Prefix); + if (in_array($event->Name, Array('OnBeforeDeleteFromLive','OnAfterClone')) ) { + $object->SwitchToLive(); + } + elseif ($event->Name == 'OnBeforeItemDelete') { + // keep current table + } + else { + $object->SwitchToTemp(); + } + + $object->Load($id); + + $fields = Array('LocalPath' => 'LocalImage', 'ThumbPath' => 'LocalThumb'); + foreach ($fields as $a_field => $mode_field) { + $file = $object->GetField($a_field); + if (!$file) continue; + $source_file = FULL_PATH.$file; + + switch ($event->Name) { + // Copy image files to pending dir and update corresponding fields in temp record + // Checking for existing files and renaming if nessessary - two users may upload same pending files at the same time! + case 'OnAfterCopyToTemp': + $new_file = IMAGES_PENDING_PATH . $this->ValidateFileName(FULL_PATH.IMAGES_PENDING_PATH, basename($file)); + $dest_file = FULL_PATH.$new_file; + copy($source_file, $dest_file); + $object->Fields[$a_field]['skip_empty'] = false; + $object->SetDBField($a_field, $new_file); + break; + + // Copy image files to live dir (checking if fileexists and renameing if nessessary) + // and update corresponding fields in temp record (which gets copied to live automatically) + case 'OnBeforeCopyToLive': + if ( $object->GetDBField($mode_field) ) { // if image is local + // rename file if it exists in live folder + $new_file = IMAGES_PATH . $this->ValidateFileName(FULL_PATH.IMAGES_PATH, basename($file)); + $dest_file = FULL_PATH.$new_file; + rename($source_file, $dest_file); + } + else { // if image is remote url - remove local file (if any), update local file field with empty value + if (file_exists($source_file)) @unlink($source_file); + $new_file = ''; + } + $object->Fields[$a_field]['skip_empty'] = false; + $object->SetDBField($a_field, $new_file); + break; + + case 'OnBeforeDeleteFromLive': // Delete image files from live folder before copying over from temp + case 'OnBeforeItemDelete': // Delete image files when deleteing Image object + @unlink(FULL_PATH.$file); + break; + + case 'OnAfterClone': // Copy files when cloning objects, renaming it on the fly + $path_info = pathinfo($file); + $new_file = $path_info['dirname'].'/'.$this->ValidateFileName(FULL_PATH.$path_info['dirname'], $path_info['basename']); + $dest_file = FULL_PATH . $new_file; + copy($source_file, $dest_file); + $object->Fields[$a_field]['skip_empty'] = false; + $object->SetDBField($a_field, $new_file); + break; + } + } + if ( in_array($event->Name, Array('OnAfterClone', 'OnBeforeCopyToLive', 'OnAfterCopyToTemp')) ) { + $object->Update(null, true); + } + } + + function ValidateFileName($path, $name) + { + $parts = pathinfo($name); + $ext = '.'.$parts['extension']; + $filename = substr($parts['basename'], 0, -strlen($ext)); + $new_name = $filename.$ext; + while ( file_exists($path.'/'.$new_name) ) + { + if ( preg_match("/({$filename}_)([0-9]*)($ext)/", $new_name, $regs) ) { + $new_name = $regs[1].($regs[2]+1).$regs[3]; + } + else { + $new_name = $filename.'_1'.$ext; + } + } + return $new_name; + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnSetPrimary(&$event) + { + $object =& $event->getObject(); + $object->SetDBField('DefaultImg', 1); + $object->Update(); + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnBeforeItemUpdate(&$event) + { + $object =& $event->getObject(); +// $parent_info = $object->getLinkedInfo(); + $id = $object->GetDBField('ResourceId'); +// $id = $parent_info['ParentId'] ? $parent_info['ParentId'] : $this->Application->GetVar('p_id'); + $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE ResourceId='.$id.' AND DefaultImg=1'; + if(!$this->Conn->GetOne($sql)) + { + $object->SetDBField('DefaultImg', 1); + } + if($object->GetDBField('DefaultImg') && $object->Validate()) + { + + $sql = 'UPDATE '.$object->TableName.' + SET DefaultImg = 0 + WHERE ResourceId = '.$id.' AND ImageId <> '.$object->GetDBField('ImageId'); + $this->Conn->Query($sql); + $object->SetDBField('Enabled', 1); + } + } + + function OnAfterItemCreate(&$event) + { + $event->CallSubEvent('OnBeforeItemUpdate'); + $object =& $event->getObject(); + $object->Update(); + } + + /** + * Deletes all selected items. + * Automatically recurse into sub-items using temp handler, and deletes sub-items + * by calling its Delete method if sub-item has AutoDelete set to true in its config file + * + * @param kEvent $event + */ + function OnMassDelete(&$event) + { + $event->status=erSUCCESS; + + $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); + + $this->StoreSelectedIDs($event); + + $event->setEventParam('ids', $this->getSelectedIDs($event) ); + $this->customProcessing($event, 'before'); + $ids = $event->getEventParam('ids'); + + $object =& $event->getObject(); + $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE DefaultImg=1'; + $primary = $this->Conn->GetOne($sql); + if( $primary && ($key = array_search($primary, $ids)) ) + { + $sql = 'SELECT ImageId FROM '.$object->TableName.' WHERE DefaultImg=0'; + $res = $this->Conn->Query($sql); + if($res) + { + unset($ids[$key]); + } + } + + if($ids) + { + $temp->DeleteItems($event->Prefix, $event->Special, $ids); + } + $this->clearSelectedIDs($event); + } + + /*function OnAfterItemLoad(&$event) + { + $object =& $event->getObject(); + + if ( $object->GetDBField('ThumbPath') || $object->GetDBField('SameImages') ) + { + // return local image or url + $path = $object->GetDBField('LocalThumb') ? PROTOCOL.SERVER_NAME.BASE_PATH.$object->GetDBField('ThumbPath') : $object->GetDBField('ThumbUrl'); + if ( $object->GetDBField('LocalThumb') && !file_exists(FULL_PATH.$object->GetDBField('ThumbPath')) ) $path = ''; + } + else { // if we need full which is not the same as thumb + $path = $object->GetDBField('LocalImage') ? PROTOCOL.SERVER_NAME.BASE_PATH.$object->GetDBField('LocalPath') : $object->GetDBField('Url'); + if ( $object->GetDBField('LocalImage') && !file_exists(FULL_PATH.$object->GetDBField('LocalPath')) ) $path = ''; + } + + $object->SetDBField('ImageUrl', $path); + }*/ + + function SetCustomQuery(&$event) + { + parent::SetCustomQuery($event); + + $types=$event->getEventParam('types'); + $except_types=$event->getEventParam('except'); + $object =& $event->getObject(); + $type_clauses = Array(); + + if( !$this->Application->IsAdmin() ) + { + $object->addFilter('active', '%1$s.Enabled = 1'); + } + + if($product_id = $event->getEventParam('product_id')) + { + $object->removeFilter('parent_filter'); + $sql = 'SELECT ResourceId FROM '.$this->Application->getUnitOption('p', 'TableName').' + WHERE ProductId = '.$product_id; + $resource_id = (int) $this->Conn->GetOne($sql); + $object->addFilter('product_images', '%1$s.ResourceId = '.$resource_id); + } + + $type_clauses['additional']['include'] = '%1$s.DefaultImg != 1'; + $type_clauses['additional']['except'] = '%1$s.DefaultImg = 1'; + $type_clauses['additional']['having_filter'] = false; + + /********************************************/ + + $includes_or_filter =& $this->Application->makeClass('kMultipleFilter'); + $includes_or_filter->setType(FLT_TYPE_OR); + + $excepts_and_filter =& $this->Application->makeClass('kMultipleFilter'); + $excepts_and_filter->setType(FLT_TYPE_AND); + + $includes_or_filter_h =& $this->Application->makeClass('kMultipleFilter'); + $includes_or_filter_h->setType(FLT_TYPE_OR); + + $excepts_and_filter_h =& $this->Application->makeClass('kMultipleFilter'); + $excepts_and_filter_h->setType(FLT_TYPE_AND); + + $except_types_array=explode(',', $types); + + if ($types){ + $types_array=explode(',', $types); + for ($i=0; $iremoveFilter('filter_'.$type); + $includes_or_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['include']); + }else{ + $includes_or_filter->removeFilter('filter_'.$type); + $includes_or_filter->addFilter('filter_'.$type, $type_clauses[$type]['include']); + } + } + } + } + + if ($except_types){ + $except_types_array=explode(',', $except_types); + for ($i=0; $iremoveFilter('filter_'.$type); + $excepts_and_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['except']); + }else{ + $excepts_and_filter->removeFilter('filter_'.$type); + $excepts_and_filter->addFilter('filter_'.$type, $type_clauses[$type]['except']); + } + } + } + } + + $object->addFilter('includes_filter', $includes_or_filter); + $object->addFilter('excepts_filter', $excepts_and_filter); + + $object->addFilter('includes_filter_h', $includes_or_filter_h, HAVING_FILTER); + $object->addFilter('excepts_filter_h', $excepts_and_filter_h, HAVING_FILTER); + } +} + +?> \ No newline at end of file