Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F772209
cat_event_handler.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Feb 1, 5:37 AM
Size
88 KB
Mime Type
text/x-php
Expires
Mon, Feb 3, 5:37 AM (3 h, 41 m)
Engine
blob
Format
Raw Data
Handle
555742
Attached To
rINP In-Portal
cat_event_handler.php
View Options
<?php
/**
* @version $Id: cat_event_handler.php 14537 2011-09-18 14:19:48Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined
(
'FULL_PATH'
)
or
die
(
'restricted access!'
);
class
kCatDBEventHandler
extends
kDBEventHandler
{
/**
* Allows to override standart permission mapping
*
*/
function
mapPermissions
()
{
parent
::
mapPermissions
();
$permissions
=
Array
(
'OnSaveSettings'
=>
Array
(
'self'
=>
'add|edit|advanced:import'
),
'OnResetSettings'
=>
Array
(
'self'
=>
'add|edit|advanced:import'
),
'OnBeforeDeleteOriginal'
=>
Array
(
'self'
=>
'edit|advanced:approve'
),
'OnCopy'
=>
Array
(
'self'
=>
true
),
'OnDownloadFile'
=>
Array
(
'self'
=>
'view'
),
'OnCancelAction'
=>
Array
(
'self'
=>
true
),
'OnItemBuild'
=>
Array
(
'self'
=>
true
),
'OnMakeVote'
=>
Array
(
'self'
=>
true
),
);
$this
->
permMapping
=
array_merge
(
$this
->
permMapping
,
$permissions
);
}
/**
* Load item if id is available
*
* @param kEvent $event
*/
function
LoadItem
(&
$event
)
{
$object
=&
$event
->
getObject
();
$id
=
$this
->
getPassedID
(
$event
);
if
(
$object
->
Load
(
$id
))
{
$actions
=&
$this
->
Application
->
recallObject
(
'kActions'
);
$actions
->
Set
(
$event
->
Prefix_Special
.
'_id'
,
$object
->
GetID
()
);
$use_pending_editing
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'UsePendingEditing'
);
if
(
$use_pending_editing
&&
$event
->
Special
!=
'original'
)
{
$this
->
Application
->
SetVar
(
$event
->
Prefix
.
'.original_id'
,
$object
->
GetDBField
(
'OrgId'
));
}
}
else
{
$object
->
setID
(
$id
);
}
}
/**
* Checks permissions of user
*
* @param kEvent $event
*/
function
CheckPermission
(&
$event
)
{
if
(!
$this
->
Application
->
isAdmin
)
{
if
(
$event
->
Name
==
'OnSetSortingDirect'
)
{
// allow sorting on front event without view permission
return
true
;
}
}
if
(
$event
->
Name
==
'OnExport'
)
{
// save category_id before doing export
$this
->
Application
->
LinkVar
(
'm_cat_id'
);
}
if
(
in_array
(
$event
->
Name
,
$this
->
_getMassPermissionEvents
()))
{
$items
=
$this
->
_getPermissionCheckInfo
(
$event
);
$perm_helper
=&
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
/* @var $perm_helper kPermissionsHelper */
if
((
$event
->
Name
==
'OnSave'
)
&&
array_key_exists
(
0
,
$items
))
{
// adding new item (ID = 0)
$perm_value
=
$perm_helper
->
AddCheckPermission
(
$items
[
0
][
'CategoryId'
],
$event
->
Prefix
)
>
0
;
}
else
{
// leave only items, that can be edited
$ids
=
Array
();
$check_method
=
in_array
(
$event
->
Name
,
Array
(
'OnMassDelete'
,
'OnCut'
))
?
'DeleteCheckPermission'
:
'ModifyCheckPermission'
;
foreach
(
$items
as
$item_id
=>
$item_data
)
{
if
(
$perm_helper
->
$check_method
(
$item_data
[
'CreatedById'
],
$item_data
[
'CategoryId'
],
$event
->
Prefix
)
>
0
)
{
$ids
[]
=
$item_id
;
}
}
if
(!
$ids
)
{
// no items left for editing -> no permission
return
$perm_helper
->
finalizePermissionCheck
(
$event
,
false
);
}
$perm_value
=
true
;
$event
->
setEventParam
(
'ids'
,
$ids
);
// will be used later by "kDBEventHandler::StoreSelectedIDs" method
}
return
$perm_helper
->
finalizePermissionCheck
(
$event
,
$perm_value
);
}
$export_events
=
Array
(
'OnSaveSettings'
,
'OnResetSettings'
,
'OnExportBegin'
);
if
(
in_array
(
$event
->
Name
,
$export_events
))
{
// when import settings before selecting target import category
return
$this
->
Application
->
CheckPermission
(
'in-portal:main_import.view'
);
}
if
(
$event
->
Name
==
'OnProcessSelected'
)
{
if
(
$this
->
Application
->
RecallVar
(
'dst_field'
)
==
'ImportCategory'
)
{
// when selecting target import category
return
$this
->
Application
->
CheckPermission
(
'in-portal:main_import.view'
);
}
}
return
parent
::
CheckPermission
(
$event
);
}
/**
* Returns events, that require item-based (not just event-name based) permission check
*
* @return Array
*/
function
_getMassPermissionEvents
()
{
return
Array
(
'OnEdit'
,
'OnSave'
,
'OnMassDelete'
,
'OnMassApprove'
,
'OnMassDecline'
,
'OnMassMoveUp'
,
'OnMassMoveDown'
,
'OnCut'
,
);
}
/**
* Returns category item IDs, that require permission checking
*
* @param kEvent $event
* @return string
*/
function
_getPermissionCheckIDs
(&
$event
)
{
if
(
$event
->
Name
==
'OnSave'
)
{
$selected_ids
=
implode
(
','
,
$this
->
getSelectedIDs
(
$event
,
true
));
if
(!
$selected_ids
)
{
$selected_ids
=
0
;
// when saving newly created item (OnPreCreate -> OnPreSave -> OnSave)
}
}
else
{
// OnEdit, OnMassDelete events, when items are checked in grid
$selected_ids
=
implode
(
','
,
$this
->
StoreSelectedIDs
(
$event
));
}
return
$selected_ids
;
}
/**
* Returns information used in permission checking
*
* @param kEvent $event
* @return Array
*/
function
_getPermissionCheckInfo
(&
$event
)
{
$perm_helper
=&
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
/* @var $perm_helper kPermissionsHelper */
// when saving data from temp table to live table check by data from temp table
$item_ids
=
$this
->
_getPermissionCheckIDs
(
$event
);
$items
=
$perm_helper
->
GetCategoryItemData
(
$event
->
Prefix
,
$item_ids
,
$event
->
Name
==
'OnSave'
);
if
(!
$items
)
{
// when item not present in temp table, then permission is not checked, because there are no data in db to check
$items_info
=
$this
->
Application
->
GetVar
(
$event
->
getPrefixSpecial
(
true
)
);
list
(
$id
,
$fields_hash
)
=
each
(
$items_info
);
if
(
array_key_exists
(
'CategoryId'
,
$fields_hash
))
{
$item_category
=
$fields_hash
[
'CategoryId'
];
}
else
{
$item_category
=
$this
->
Application
->
GetVar
(
'm_cat_id'
);
}
$items
[
$id
]
=
Array
(
'CreatedById'
=>
$this
->
Application
->
RecallVar
(
'use_id'
),
'CategoryId'
=>
$item_category
,
);
}
return
$items
;
}
/**
* Add selected items to clipboard with mode = COPY (CLONE)
*
* @param kEvent $event
*/
function
OnCopy
(&
$event
)
{
$this
->
Application
->
RemoveVar
(
'clipboard'
);
$clipboard_helper
=&
$this
->
Application
->
recallObject
(
'ClipboardHelper'
);
$clipboard_helper
->
setClipboard
(
$event
,
'copy'
,
$this
->
StoreSelectedIDs
(
$event
));
$this
->
clearSelectedIDs
(
$event
);
}
/**
* Add selected items to clipboard with mode = CUT
*
* @param kEvent $event
*/
function
OnCut
(&
$event
)
{
$this
->
Application
->
RemoveVar
(
'clipboard'
);
$clipboard_helper
=&
$this
->
Application
->
recallObject
(
'ClipboardHelper'
);
$clipboard_helper
->
setClipboard
(
$event
,
'cut'
,
$this
->
StoreSelectedIDs
(
$event
));
$this
->
clearSelectedIDs
(
$event
);
}
/**
* Checks permission for OnPaste event
*
* @param kEvent $event
* @return bool
*/
function
_checkPastePermission
(&
$event
)
{
$perm_helper
=&
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
/* @var $perm_helper kPermissionsHelper */
$category_id
=
$this
->
Application
->
GetVar
(
'm_cat_id'
);
if
(
$perm_helper
->
AddCheckPermission
(
$category_id
,
$event
->
Prefix
)
==
0
)
{
// no items left for editing -> no permission
return
$perm_helper
->
finalizePermissionCheck
(
$event
,
false
);
}
return
true
;
}
/**
* Performs category item paste
*
* @param kEvent $event
*/
function
OnPaste
(&
$event
)
{
if
(
$this
->
Application
->
CheckPermission
(
'SYSTEM_ACCESS.READONLY'
,
1
)
||
!
$this
->
_checkPastePermission
(
$event
))
{
$event
->
status
=
erFAIL
;
return
;
}
$clipboard_data
=
$event
->
getEventParam
(
'clipboard_data'
);
if
(!
$clipboard_data
[
'cut'
]
&&
!
$clipboard_data
[
'copy'
])
{
return
false
;
}
if
(
$clipboard_data
[
'copy'
])
{
$temp
=&
$this
->
Application
->
recallObject
(
$event
->
getPrefixSpecial
().
'_TempHandler'
,
'kTempTablesHandler'
);
/* @var $temp kTempTablesHandler */
$this
->
Application
->
SetVar
(
'ResetCatBeforeClone'
,
1
);
// used in "kCatDBEventHandler::OnBeforeClone"
$temp
->
CloneItems
(
$event
->
Prefix
,
$event
->
Special
,
$clipboard_data
[
'copy'
]);
}
if
(
$clipboard_data
[
'cut'
])
{
$object
=&
$this
->
Application
->
recallObject
(
$event
->
getPrefixSpecial
().
'.item'
,
$event
->
Prefix
,
Array
(
'skip_autoload'
=>
true
));
foreach
(
$clipboard_data
[
'cut'
]
as
$id
)
{
$object
->
Load
(
$id
);
$object
->
MoveToCat
();
}
}
}
/**
* 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
)
{
if
(
$this
->
Application
->
CheckPermission
(
'SYSTEM_ACCESS.READONLY'
,
1
))
{
$event
->
status
=
erFAIL
;
return
;
}
$event
->
status
=
erSUCCESS
;
$ids
=
$this
->
StoreSelectedIDs
(
$event
);
$to_delete
=
array
();
if
(
$recycle_bin
=
$this
->
Application
->
ConfigValue
(
'RecycleBinFolder'
))
{
$rb
=&
$this
->
Application
->
recallObject
(
'c.recycle'
,
null
,
array
(
'skip_autoload'
=>
true
));
$rb
->
Load
(
$recycle_bin
);
$object
=&
$this
->
Application
->
recallObject
(
$event
->
Prefix
.
'.recycleitem'
,
null
,
Array
(
'skip_autoload'
=>
true
));
foreach
(
$ids
as
$id
)
{
$object
->
Load
(
$id
);
if
(
preg_match
(
'/^'
.
preg_quote
(
$rb
->
GetDBField
(
'ParentPath'
),
'/'
).
'/'
,
$object
->
GetDBField
(
'ParentPath'
)))
{
$to_delete
[]
=
$id
;
continue
;
}
$object
->
MoveToCat
(
$recycle_bin
);
}
$ids
=
$to_delete
;
}
$temp
=&
$this
->
Application
->
recallObject
(
$event
->
getPrefixSpecial
().
'_TempHandler'
,
'kTempTablesHandler'
);
$event
->
setEventParam
(
'ids'
,
$ids
);
$this
->
customProcessing
(
$event
,
'before'
);
$ids
=
$event
->
getEventParam
(
'ids'
);
if
(
$ids
)
{
$temp
->
DeleteItems
(
$event
->
Prefix
,
$event
->
Special
,
$ids
);
}
$this
->
clearSelectedIDs
(
$event
);
}
/**
* Return type clauses for list bulding on front
*
* @param kEvent $event
* @return Array
*/
function
getTypeClauses
(&
$event
)
{
$types
=
$event
->
getEventParam
(
'types'
);
$types
=
$types
?
explode
(
','
,
$types
)
:
Array
();
$except_types
=
$event
->
getEventParam
(
'except'
);
$except_types
=
$except_types
?
explode
(
','
,
$except_types
)
:
Array
();
$type_clauses
=
Array
();
$user_id
=
$this
->
Application
->
RecallVar
(
'user_id'
);
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
$type_clauses
[
'my_items'
][
'include'
]
=
'%1$s.'
.
$owner_field
.
' = '
.
$user_id
;
$type_clauses
[
'my_items'
][
'except'
]
=
'%1$s.'
.
$owner_field
.
' <> '
.
$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
;
$type_clauses
[
'hot'
][
'include'
]
=
'`IsHot` = 1 AND PrimaryCat = 1'
;
$type_clauses
[
'hot'
][
'except'
]
=
'`IsHot`! = 1 AND PrimaryCat = 1'
;
$type_clauses
[
'hot'
][
'having_filter'
]
=
true
;
$type_clauses
[
'pop'
][
'include'
]
=
'`IsPop` = 1 AND PrimaryCat = 1'
;
$type_clauses
[
'pop'
][
'except'
]
=
'`IsPop`! = 1 AND PrimaryCat = 1'
;
$type_clauses
[
'pop'
][
'having_filter'
]
=
true
;
$type_clauses
[
'new'
][
'include'
]
=
'`IsNew` = 1 AND PrimaryCat = 1'
;
$type_clauses
[
'new'
][
'except'
]
=
'`IsNew`! = 1 AND PrimaryCat = 1'
;
$type_clauses
[
'new'
][
'having_filter'
]
=
true
;
$type_clauses
[
'displayed'
][
'include'
]
=
''
;
$displayed
=
$this
->
Application
->
GetVar
(
$event
->
Prefix
.
'_displayed_ids'
);
if
(
$displayed
)
{
$id_field
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'IDField'
);
$type_clauses
[
'displayed'
][
'except'
]
=
'%1$s.'
.
$id_field
.
' NOT IN ('
.
$displayed
.
')'
;
}
else
{
$type_clauses
[
'displayed'
][
'except'
]
=
''
;
}
$type_clauses
[
'displayed'
][
'having_filter'
]
=
false
;
if
(
in_array
(
'search'
,
$types
)
||
in_array
(
'search'
,
$except_types
))
{
$event_mapping
=
Array
(
'simple'
=>
'OnSimpleSearch'
,
'subsearch'
=>
'OnSubSearch'
,
'advanced'
=>
'OnAdvancedSearch'
);
$type
=
$this
->
Application
->
GetVar
(
'search_type'
,
'simple'
);
if
(
$keywords
=
$event
->
getEventParam
(
'keyword_string'
))
{
// processing keyword_string param of ListProducts tag
$this
->
Application
->
SetVar
(
'keywords'
,
$keywords
);
$type
=
'simple'
;
}
$search_event
=
$event_mapping
[
$type
];
$this
->
$search_event
(
$event
);
$object
=&
$event
->
getObject
();
/* @var $object kDBList */
$search_sql
=
' FROM '
.
TABLE_PREFIX
.
'ses_'
.
$this
->
Application
->
GetSID
()
.
'_'
.
TABLE_PREFIX
.
'Search
search_result LEFT JOIN %1$s ON %1$s.ResourceId = search_result.ResourceId'
;
$sql
=
str_replace
(
'FROM %1$s'
,
$search_sql
,
$object
->
SelectClause
);
$object
->
SetSelectSQL
(
$sql
);
$object
->
addCalculatedField
(
'Relevance'
,
'search_result.Relevance'
);
$object
->
AddOrderField
(
'search_result.Relevance'
,
'desc'
,
true
);
$type_clauses
[
'search'
][
'include'
]
=
'PrimaryCat = 1 AND ('
.
TABLE_PREFIX
.
'Category.Status = '
.
STATUS_ACTIVE
.
')'
;
$type_clauses
[
'search'
][
'except'
]
=
'PrimaryCat = 1 AND ('
.
TABLE_PREFIX
.
'Category.Status = '
.
STATUS_ACTIVE
.
')'
;
$type_clauses
[
'search'
][
'having_filter'
]
=
false
;
}
if
(
in_array
(
'related'
,
$types
)
||
in_array
(
'related'
,
$except_types
))
{
$related_to
=
$event
->
getEventParam
(
'related_to'
);
if
(!
$related_to
)
{
$related_prefix
=
$event
->
Prefix
;
}
else
{
$sql
=
'SELECT Prefix
FROM '
.
TABLE_PREFIX
.
'ItemTypes
WHERE ItemName = '
.
$this
->
Conn
->
qstr
(
$related_to
);
$related_prefix
=
$this
->
Conn
->
GetOne
(
$sql
);
}
$rel_table
=
$this
->
Application
->
getUnitOption
(
'rel'
,
'TableName'
);
$item_type
=
(
int
)
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ItemType'
);
if
(
$item_type
==
0
)
{
trigger_error
(
'<strong>ItemType</strong> not defined for prefix <strong>'
.
$event
->
Prefix
.
'</strong>'
,
E_USER_WARNING
);
}
// process case, then this list is called inside another list
$prefix_special
=
$event
->
getEventParam
(
'PrefixSpecial'
);
if
(!
$prefix_special
)
{
$prefix_special
=
$this
->
Application
->
Parser
->
GetParam
(
'PrefixSpecial'
);
}
$id
=
false
;
if
(
$prefix_special
!==
false
)
{
$processed_prefix
=
$this
->
Application
->
processPrefix
(
$prefix_special
);
if
(
$processed_prefix
[
'prefix'
]
==
$related_prefix
)
{
// printing related categories within list of items (not on details page)
$list
=&
$this
->
Application
->
recallObject
(
$prefix_special
);
/* @var $list kDBList */
$id
=
$list
->
GetID
();
}
}
if
(
$id
===
false
)
{
// printing related categories for single item (possibly on details page)
if
(
$related_prefix
==
'c'
)
{
$id
=
$this
->
Application
->
GetVar
(
'm_cat_id'
);
}
else
{
$id
=
$this
->
Application
->
GetVar
(
$related_prefix
.
'_id'
);
}
}
$p_item
=&
$this
->
Application
->
recallObject
(
$related_prefix
.
'.current'
,
null
,
Array
(
'skip_autoload'
=>
true
));
$p_item
->
Load
(
(
int
)
$id
);
$p_resource_id
=
$p_item
->
GetDBField
(
'ResourceId'
);
$sql
=
'SELECT SourceId, TargetId FROM '
.
$rel_table
.
'
WHERE
(Enabled = 1)
AND (
(Type = 0 AND SourceId = '
.
$p_resource_id
.
' AND TargetType = '
.
$item_type
.
')
OR
(Type = 1
AND (
(SourceId = '
.
$p_resource_id
.
' AND TargetType = '
.
$item_type
.
')
OR
(TargetId = '
.
$p_resource_id
.
' AND SourceType = '
.
$item_type
.
')
)
)
)'
;
$related_ids_array
=
$this
->
Conn
->
Query
(
$sql
);
$related_ids
=
Array
();
foreach
(
$related_ids_array
as
$key
=>
$record
)
{
$related_ids
[]
=
$record
[
$record
[
'SourceId'
]
==
$p_resource_id
?
'TargetId'
:
'SourceId'
];
}
if
(
count
(
$related_ids
)
>
0
)
{
$type_clauses
[
'related'
][
'include'
]
=
'%1$s.ResourceId IN ('
.
implode
(
','
,
$related_ids
).
') AND PrimaryCat = 1'
;
$type_clauses
[
'related'
][
'except'
]
=
'%1$s.ResourceId NOT IN ('
.
implode
(
','
,
$related_ids
).
') AND PrimaryCat = 1'
;
}
else
{
$type_clauses
[
'related'
][
'include'
]
=
'0'
;
$type_clauses
[
'related'
][
'except'
]
=
'1'
;
}
$type_clauses
[
'related'
][
'having_filter'
]
=
false
;
}
if
(
in_array
(
'favorites'
,
$types
)
||
in_array
(
'favorites'
,
$except_types
))
{
$sql
=
'SELECT ResourceId
FROM '
.
$this
->
Application
->
getUnitOption
(
'fav'
,
'TableName'
).
'
WHERE PortalUserId = '
.
$this
->
Application
->
RecallVar
(
'user_id'
);
$favorite_ids
=
$this
->
Conn
->
GetCol
(
$sql
);
if
(
$favorite_ids
)
{
$type_clauses
[
'favorites'
][
'include'
]
=
'%1$s.ResourceId IN ('
.
implode
(
','
,
$favorite_ids
).
') AND PrimaryCat = 1'
;
$type_clauses
[
'favorites'
][
'except'
]
=
'%1$s.ResourceId NOT IN ('
.
implode
(
','
,
$favorite_ids
).
') AND PrimaryCat = 1'
;
}
else
{
$type_clauses
[
'favorites'
][
'include'
]
=
0
;
$type_clauses
[
'favorites'
][
'except'
]
=
1
;
}
$type_clauses
[
'favorites'
][
'having_filter'
]
=
false
;
}
return
$type_clauses
;
}
/**
* Returns SQL clause, that will help to select only data from specified category & it's children
*
* @param int $category_id
* @return string
*/
function
getCategoryLimitClause
(
$category_id
)
{
if
(!
$category_id
)
{
return
false
;
}
$tree_indexes
=
$this
->
Application
->
getTreeIndex
(
$category_id
);
if
(!
$tree_indexes
)
{
// id of non-existing category was given
return
'FALSE'
;
}
return
TABLE_PREFIX
.
'Category.TreeLeft BETWEEN '
.
$tree_indexes
[
'TreeLeft'
].
' AND '
.
$tree_indexes
[
'TreeRight'
];
}
/**
* Apply filters to list
*
* @param kEvent $event
*/
function
SetCustomQuery
(&
$event
)
{
parent
::
SetCustomQuery
(
$event
);
$object
=&
$event
->
getObject
();
/* @var $object kDBList */
// add category filter if needed
if
(
$event
->
Special
!=
'showall'
&&
$event
->
Special
!=
'user'
)
{
if
(
$event
->
getEventParam
(
'parent_cat_id'
)
!==
false
)
{
$parent_cat_id
=
$event
->
getEventParam
(
'parent_cat_id'
);
}
else
{
$parent_cat_id
=
$this
->
Application
->
GetVar
(
'c_id'
);
if
(!
$parent_cat_id
)
{
$parent_cat_id
=
$this
->
Application
->
GetVar
(
'm_cat_id'
);
}
if
(!
$parent_cat_id
)
{
$parent_cat_id
=
0
;
}
}
if
(
"$parent_cat_id"
==
'0'
)
{
// replace "0" category with "Content" category id (this way template
$parent_cat_id
=
$this
->
Application
->
getBaseCategory
();
}
if
((
string
)
$parent_cat_id
!=
'any'
)
{
if
(
$event
->
getEventParam
(
'recursive'
))
{
$filter_clause
=
$this
->
getCategoryLimitClause
(
$parent_cat_id
);
if
(
$filter_clause
!==
false
)
{
$object
->
addFilter
(
'category_filter'
,
$filter_clause
);
}
$object
->
addFilter
(
'primary_filter'
,
'PrimaryCat = 1'
);
}
else
{
$object
->
addFilter
(
'category_filter'
,
TABLE_PREFIX
.
'CategoryItems.CategoryId = '
.
$parent_cat_id
);
}
}
else
{
$object
->
addFilter
(
'primary_filter'
,
'PrimaryCat = 1'
);
}
}
else
{
$object
->
addFilter
(
'primary_filter'
,
'PrimaryCat = 1'
);
// if using recycle bin don't show items from there
$recycle_bin
=
$this
->
Application
->
ConfigValue
(
'RecycleBinFolder'
);
if
(
$recycle_bin
)
{
$object
->
addFilter
(
'recyclebin_filter'
,
TABLE_PREFIX
.
'CategoryItems.CategoryId <> '
.
$recycle_bin
);
}
}
if
(
$event
->
Special
==
'user'
)
{
$editable_user
=
$this
->
Application
->
GetVar
(
'u_id'
);
$object
->
addFilter
(
'owner_filter'
,
'%1$s.'
.
$this
->
getOwnerField
(
$event
->
Prefix
).
' = '
.
$editable_user
);
}
// add permission filter
if
(
$this
->
Application
->
RecallVar
(
'user_id'
)
==
USER_ROOT
)
{
// for "root" CATEGORY.VIEW permission is checked for items lists too
$view_perm
=
1
;
}
else
{
// for any real user itemlist view permission is checked instead of CATEGORY.VIEW
$count_helper
=&
$this
->
Application
->
recallObject
(
'CountHelper'
);
/* @var $count_helper kCountHelper */
list
(
$view_perm
,
$view_filter
)
=
$count_helper
->
GetPermissionClause
(
$event
->
Prefix
,
'perm'
);
$object
->
addFilter
(
'perm_filter2'
,
$view_filter
);
}
$object
->
addFilter
(
'perm_filter'
,
'perm.PermId = '
.
$view_perm
);
$types
=
$event
->
getEventParam
(
'types'
);
$this
->
applyItemStatusFilter
(
$object
,
$types
);
$except_types
=
$event
->
getEventParam
(
'except'
);
$type_clauses
=
$this
->
getTypeClauses
(
$event
);
// convert prepared type clauses into list filters
$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
);
if
(
$types
)
{
$types_array
=
explode
(
','
,
$types
);
for
(
$i
=
0
;
$i
<
sizeof
(
$types_array
);
$i
++)
{
$type
=
trim
(
$types_array
[
$i
]);
if
(
isset
(
$type_clauses
[
$type
]))
{
if
(
$type_clauses
[
$type
][
'having_filter'
])
{
$includes_or_filter_h
->
removeFilter
(
'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
;
$i
<
sizeof
(
$except_types_array
);
$i
++)
{
$type
=
trim
(
$except_types_array
[
$i
]);
if
(
isset
(
$type_clauses
[
$type
]))
{
if
(
$type_clauses
[
$type
][
'having_filter'
])
{
$excepts_and_filter_h
->
removeFilter
(
'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'
]);
}
}
}
}
/*if (!$this->Application->isAdminUser) {
$object->addFilter('expire_filter', '%1$s.Expire IS NULL OR %1$s.Expire > UNIX_TIMESTAMP()');
}*/
/*$list_type = $event->getEventParam('ListType');
switch($list_type)
{
case 'favorites':
$fav_table = $this->Application->getUnitOption('fav','TableName');
$user_id =& $this->Application->RecallVar('user_id');
$sql = 'SELECT DISTINCT f.ResourceId
FROM '.$fav_table.' f
LEFT JOIN '.$object->TableName.' p ON p.ResourceId = f.ResourceId
WHERE f.PortalUserId = '.$user_id;
$ids = $this->Conn->GetCol($sql);
if(!$ids) $ids = Array(-1);
$object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.PrimaryCat = 1');
$object->addFilter('favorites_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')');
break;
case 'search':
$search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
$sql = ' SELECT DISTINCT ResourceId
FROM '.$search_results_table.'
WHERE ItemType=11';
$ids = $this->Conn->GetCol($sql);
if(!$ids) $ids = Array(-1);
$object->addFilter('search_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')');
break;
} */
$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
);
}
/**
* 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
->
isAdminUser
)
{
$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 = '
.
STATUS_ACTIVE
.
') AND ('
.
TABLE_PREFIX
.
'Category.Status = '
.
STATUS_ACTIVE
.
')'
);
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
))
{
$owner_field
=
$this
->
getOwnerField
(
$object
->
Prefix
);
$sql
.=
' AND '
.
$owner_field
.
' = '
.
$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
* @param kEvent $event
*/
function
prepareObject
(&
$object
,
&
$event
)
{
$this
->
prepareItemStatuses
(
$event
);
$object
->
addCalculatedField
(
'CachedNavbar'
,
'l'
.
$this
->
Application
->
GetVar
(
'm_lang'
).
'_CachedNavbar'
);
if
(
$event
->
Special
==
'export'
||
$event
->
Special
==
'import'
)
{
$export_helper
=&
$this
->
Application
->
recallObject
(
'CatItemExportHelper'
);
$export_helper
->
prepareExportColumns
(
$event
);
}
}
/**
* Creates calculated fields for all item statuses based on config settings
*
* @param kEvent $event
*/
function
prepareItemStatuses
(&
$event
)
{
$object
=&
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
)
);
$property_map
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ItemPropertyMappings'
);
if
(!
$property_map
)
{
return
;
}
// new items
$object
->
addCalculatedField
(
'IsNew'
,
' IF(%1$s.NewItem = 2,
IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '
.
$this
->
Application
->
ConfigValue
(
$property_map
[
'NewDays'
]).
'*3600*24), 1, 0),
%1$s.NewItem
)'
);
// hot items (cache updated every hour)
if
(
$this
->
Application
->
isCachingType
(
CACHING_TYPE_MEMORY
))
{
$serial_name
=
$this
->
Application
->
incrementCacheSerial
(
$event
->
Prefix
,
null
,
false
);
$hot_limit
=
$this
->
Application
->
getCache
(
$property_map
[
'HotLimit'
]
.
'[%'
.
$serial_name
.
'%]'
);
}
else
{
$hot_limit
=
$this
->
Application
->
getDBCache
(
$property_map
[
'HotLimit'
]);
}
if
(
$hot_limit
===
false
)
{
$hot_limit
=
$this
->
CalculateHotLimit
(
$event
);
}
$object
->
addCalculatedField
(
'IsHot'
,
' IF(%1$s.HotItem = 2,
IF(%1$s.'
.
$property_map
[
'ClickField'
].
' >= '
.
$hot_limit
.
', 1, 0),
%1$s.HotItem
)'
);
// popular items
$object
->
addCalculatedField
(
'IsPop'
,
' IF(%1$s.PopItem = 2,
IF(%1$s.CachedVotesQty >= '
.
$this
->
Application
->
ConfigValue
(
$property_map
[
'MinPopVotes'
]).
' AND %1$s.CachedRating >= '
.
$this
->
Application
->
ConfigValue
(
$property_map
[
'MinPopRating'
]).
', 1, 0),
%1$s.PopItem)'
);
}
function
CalculateHotLimit
(&
$event
)
{
$property_map
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ItemPropertyMappings'
);
if
(!
$property_map
)
{
return
;
}
$click_field
=
$property_map
[
'ClickField'
];
$last_hot
=
$this
->
Application
->
ConfigValue
(
$property_map
[
'MaxHotNumber'
])
-
1
;
$sql
=
'SELECT '
.
$click_field
.
' FROM '
.
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'TableName'
).
'
ORDER BY '
.
$click_field
.
' DESC
LIMIT '
.
$last_hot
.
', 1'
;
$res
=
$this
->
Conn
->
GetCol
(
$sql
);
$hot_limit
=
(
double
)
array_shift
(
$res
);
if
(
$this
->
Application
->
isCachingType
(
CACHING_TYPE_MEMORY
))
{
$serial_name
=
$this
->
Application
->
incrementCacheSerial
(
$event
->
Prefix
,
null
,
false
);
$this
->
Application
->
setCache
(
$property_map
[
'HotLimit'
]
.
'[%'
.
$serial_name
.
'%]'
,
$hot_limit
);
}
else
{
$this
->
Application
->
setDBCache
(
$property_map
[
'HotLimit'
],
$hot_limit
,
3600
);
}
return
$hot_limit
;
}
/**
* Moves item to preferred category, updates item hits
*
* @param kEvent $event
*/
function
OnBeforeItemUpdate
(&
$event
)
{
parent
::
OnBeforeItemUpdate
(
$event
);
$object
=&
$event
->
getObject
();
/* @var $object kCatDBItem */
// update hits field
$property_map
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ItemPropertyMappings'
);
if
(
$property_map
)
{
$click_field
=
$property_map
[
'ClickField'
];
if
(
$this
->
Application
->
isAdminUser
&&
(
$this
->
Application
->
GetVar
(
$click_field
.
'_original'
)
!==
false
)
&&
floor
(
$this
->
Application
->
GetVar
(
$click_field
.
'_original'
))
!=
$object
->
GetDBField
(
$click_field
)
)
{
$sql
=
'SELECT MAX('
.
$click_field
.
') FROM '
.
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'TableName'
).
'
WHERE FLOOR('
.
$click_field
.
') = '
.
$object
->
GetDBField
(
$click_field
);
$hits
=
(
$res
=
$this
->
Conn
->
GetOne
(
$sql
)
)
?
$res
+
0.000001
:
$object
->
GetDBField
(
$click_field
);
$object
->
SetDBField
(
$click_field
,
$hits
);
}
}
// change category
$target_category
=
$object
->
GetDBField
(
'CategoryId'
);
if
(
$object
->
GetOriginalField
(
'CategoryId'
)
!=
$target_category
)
{
$object
->
MoveToCat
(
$target_category
);
}
}
/**
* Load price from temp table if product mode is temp table
*
* @param kEvent $event
*/
function
OnAfterItemLoad
(&
$event
)
{
$special
=
substr
(
$event
->
Special
,
-
6
);
$object
=&
$event
->
getObject
();
/* @var $object kCatDBItem */
if
(
$special
==
'import'
||
$special
==
'export'
)
{
$image_data
=
$object
->
getPrimaryImageData
();
if
(
$image_data
)
{
$thumbnail_image
=
$image_data
[
$image_data
[
'LocalThumb'
]
?
'ThumbPath'
:
'ThumbUrl'
];
if
(
$image_data
[
'SameImages'
])
{
$full_image
=
''
;
}
else
{
$full_image
=
$image_data
[
$image_data
[
'LocalImage'
]
?
'LocalPath'
:
'Url'
];
}
$object
->
SetDBField
(
'ThumbnailImage'
,
$thumbnail_image
);
$object
->
SetDBField
(
'FullImage'
,
$full_image
);
$object
->
SetDBField
(
'ImageAlt'
,
$image_data
[
'AltName'
]);
}
}
// substituiting pending status value for pending editing
if
(
$object
->
HasField
(
'OrgId'
)
&&
$object
->
GetDBField
(
'OrgId'
)
>
0
&&
$object
->
GetDBField
(
'Status'
)
==
-
2
)
{
$options
=
$object
->
Fields
[
'Status'
][
'options'
];
foreach
(
$options
as
$key
=>
$val
)
{
if
(
$key
==
2
)
$key
=
-
2
;
$new_options
[
$key
]
=
$val
;
}
$object
->
Fields
[
'Status'
][
'options'
]
=
$new_options
;
}
if
(
!
$this
->
Application
->
isAdmin
)
{
// linking existing images for item with virtual fields
$image_helper
=&
$this
->
Application
->
recallObject
(
'ImageHelper'
);
/* @var $image_helper ImageHelper */
$image_helper
->
LoadItemImages
(
$object
);
// linking existing files for item with virtual fields
$file_helper
=&
$this
->
Application
->
recallObject
(
'FileHelper'
);
/* @var $file_helper FileHelper */
$file_helper
->
LoadItemFiles
(
$object
);
}
if
(
array_key_exists
(
'MoreCategories'
,
$object
->
VirtualFields
)
)
{
// set item's additional categories to virtual field (used in editing)
$item_categories
=
$this
->
getItemCategories
(
$object
->
GetDBField
(
'ResourceId'
));
$object
->
SetDBField
(
'MoreCategories'
,
$item_categories
?
'|'
.
implode
(
'|'
,
$item_categories
).
'|'
:
''
);
}
}
function
OnAfterItemUpdate
(&
$event
)
{
$this
->
CalculateHotLimit
(
$event
);
if
(
substr
(
$event
->
Special
,
-
6
)
==
'import'
)
{
$this
->
setCustomExportColumns
(
$event
);
}
$object
=&
$event
->
getObject
();
/* @var $object kDBItem */
if
(
!
$this
->
Application
->
isAdmin
)
{
$image_helper
=&
$this
->
Application
->
recallObject
(
'ImageHelper'
);
/* @var $image_helper ImageHelper */
// process image upload in virtual fields
$image_helper
->
SaveItemImages
(
$object
);
$file_helper
=&
$this
->
Application
->
recallObject
(
'FileHelper'
);
/* @var $file_helper FileHelper */
// process file upload in virtual fields
$file_helper
->
SaveItemFiles
(
$object
);
if
(
$event
->
Special
!=
'-item'
)
{
// don't touch categories during cloning
$this
->
processAdditionalCategories
(
$object
,
'update'
);
}
}
$recycle_bin
=
$this
->
Application
->
ConfigValue
(
'RecycleBinFolder'
);
if
(
$this
->
Application
->
isAdminUser
&&
$recycle_bin
)
{
$sql
=
'SELECT CategoryId
FROM '
.
$this
->
Application
->
getUnitOption
(
'ci'
,
'TableName'
)
.
'
WHERE ItemResourceId = '
.
$object
->
GetDBField
(
'ResourceId'
)
.
' AND PrimaryCat = 1'
;
$primary_category
=
$this
->
Conn
->
GetOne
(
$sql
);
if
(
$primary_category
==
$recycle_bin
)
{
$event
->
CallSubEvent
(
'OnAfterItemDelete'
);
}
}
}
/**
* sets values for import process
*
* @param kEvent $event
*/
function
OnAfterItemCreate
(&
$event
)
{
if
(
substr
(
$event
->
Special
,
-
6
)
==
'import'
)
{
$this
->
setCustomExportColumns
(
$event
);
}
if
(
!
$this
->
Application
->
isAdmin
)
{
$object
=&
$event
->
getObject
();
/* @var $object kDBItem */
$image_helper
=&
$this
->
Application
->
recallObject
(
'ImageHelper'
);
/* @var $image_helper ImageHelper */
// process image upload in virtual fields
$image_helper
->
SaveItemImages
(
$object
);
$file_helper
=&
$this
->
Application
->
recallObject
(
'FileHelper'
);
/* @var $file_helper FileHelper */
// process file upload in virtual fields
$file_helper
->
SaveItemFiles
(
$object
);
if
(
$event
->
Special
!=
'-item'
)
{
// don't touch categories during cloning
$this
->
processAdditionalCategories
(
$object
,
'create'
);
}
}
}
/**
* Make record to search log
*
* @param string $keywords
* @param int $search_type 0 - simple search, 1 - advanced search
*/
function
saveToSearchLog
(
$keywords
,
$search_type
=
0
)
{
// don't save keywords for each module separately, just one time
// static variable can't help here, because each module uses it's own class instance !
if
(!
$this
->
Application
->
GetVar
(
'search_logged'
))
{
$sql
=
'UPDATE '
.
TABLE_PREFIX
.
'SearchLog
SET Indices = Indices + 1
WHERE Keyword = '
.
$this
->
Conn
->
qstr
(
$keywords
).
' AND SearchType = '
.
$search_type
;
// 0 - simple search, 1 - advanced search
$this
->
Conn
->
Query
(
$sql
);
if
(
$this
->
Conn
->
getAffectedRows
()
==
0
)
{
$fields_hash
=
Array
(
'Keyword'
=>
$keywords
,
'Indices'
=>
1
,
'SearchType'
=>
$search_type
);
$this
->
Conn
->
doInsert
(
$fields_hash
,
TABLE_PREFIX
.
'SearchLog'
);
}
$this
->
Application
->
SetVar
(
'search_logged'
,
1
);
}
}
/**
* Makes simple search for category items
* based on keywords string
*
* @param kEvent $event
*/
function
OnSimpleSearch
(&
$event
)
{
$event
->
redirect
=
false
;
$search_table
=
TABLE_PREFIX
.
'ses_'
.
$this
->
Application
->
GetSID
().
'_'
.
TABLE_PREFIX
.
'Search'
;
$keywords
=
unhtmlentities
(
trim
(
$this
->
Application
->
GetVar
(
'keywords'
))
);
$query_object
=&
$this
->
Application
->
recallObject
(
'HTTPQuery'
);
$sql
=
'SHOW TABLES LIKE "'
.
$search_table
.
'"'
;
if
(!
isset
(
$query_object
->
Get
[
'keywords'
])
&&
!
isset
(
$query_object
->
Post
[
'keywords'
])
&&
$this
->
Conn
->
Query
(
$sql
))
{
return
;
// used when navigating by pages or changing sorting in search results
}
if
(!
$keywords
||
strlen
(
$keywords
)
<
$this
->
Application
->
ConfigValue
(
'Search_MinKeyword_Length'
))
{
$this
->
Conn
->
Query
(
'DROP TABLE IF EXISTS '
.
$search_table
);
$this
->
Application
->
SetVar
(
'keywords_too_short'
,
1
);
return
;
// if no or too short keyword entered, doing nothing
}
$this
->
Application
->
StoreVar
(
'keywords'
,
$keywords
);
$this
->
saveToSearchLog
(
$keywords
,
0
);
// 0 - simple search, 1 - advanced search
$event
->
setPseudoClass
(
'_List'
);
$object
=&
$event
->
getObject
();
/* @var $object kDBList */
$this
->
Application
->
SetVar
(
$event
->
getPrefixSpecial
().
'_Page'
,
1
);
$lang
=
$this
->
Application
->
GetVar
(
'm_lang'
);
$items_table
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'TableName'
);
$module_name
=
$this
->
Application
->
findModule
(
'Var'
,
$event
->
Prefix
,
'Name'
);
$sql
=
'SELECT *
FROM '
.
$this
->
Application
->
getUnitOption
(
'confs'
,
'TableName'
)
.
'
WHERE ModuleName = '
.
$this
->
Conn
->
qstr
(
$module_name
)
.
' AND SimpleSearch = 1'
;
$search_config
=
$this
->
Conn
->
Query
(
$sql
,
'FieldName'
);
$field_list
=
array_keys
(
$search_config
);
$join_clauses
=
Array
();
// field processing
$weight_sum
=
0
;
$alias_counter
=
0
;
$custom_fields
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'CustomFields'
);
if
(
$custom_fields
)
{
$custom_table
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
.
'-cdata'
,
'TableName'
);
$join_clauses
[]
=
' LEFT JOIN '
.
$custom_table
.
' custom_data ON '
.
$items_table
.
'.ResourceId = custom_data.ResourceId'
;
}
// what field in search config becomes what field in sql (key - new field, value - old field (from searchconfig table))
$search_config_map
=
Array
();
foreach
(
$field_list
as
$key
=>
$field
)
{
$options
=
$object
->
getFieldOptions
(
$field
);
$local_table
=
TABLE_PREFIX
.
$search_config
[
$field
][
'TableName'
];
$weight_sum
+=
$search_config
[
$field
][
'Priority'
];
// counting weight sum; used when making relevance clause
// processing multilingual fields
if
(
getArrayValue
(
$options
,
'formatter'
)
==
'kMultiLanguage'
)
{
$field_list
[
$key
.
'_primary'
]
=
'l'
.
$this
->
Application
->
GetDefaultLanguageId
().
'_'
.
$field
;
$field_list
[
$key
]
=
'l'
.
$lang
.
'_'
.
$field
;
if
(!
isset
(
$search_config
[
$field
][
'ForeignField'
]))
{
$field_list
[
$key
.
'_primary'
]
=
$local_table
.
'.'
.
$field_list
[
$key
.
'_primary'
];
$search_config_map
[
$field_list
[
$key
.
'_primary'
]
]
=
$field
;
}
}
// processing fields from other tables
if
(
$foreign_field
=
$search_config
[
$field
][
'ForeignField'
])
{
$exploded
=
explode
(
':'
,
$foreign_field
,
2
);
if
(
$exploded
[
0
]
==
'CALC'
)
{
// ignoring having type clauses in simple search
unset
(
$field_list
[
$key
]);
continue
;
}
else
{
$multi_lingual
=
false
;
if
(
$exploded
[
0
]
==
'MULTI'
)
{
$multi_lingual
=
true
;
$foreign_field
=
$exploded
[
1
];
}
$exploded
=
explode
(
'.'
,
$foreign_field
);
// format: table.field_name
$foreign_table
=
TABLE_PREFIX
.
$exploded
[
0
];
$alias_counter
++;
$alias
=
't'
.
$alias_counter
;
if
(
$multi_lingual
)
{
$field_list
[
$key
]
=
$alias
.
'.'
.
'l'
.
$lang
.
'_'
.
$exploded
[
1
];
$field_list
[
$key
.
'_primary'
]
=
'l'
.
$this
->
Application
->
GetDefaultLanguageId
().
'_'
.
$field
;
$search_config_map
[
$field_list
[
$key
]
]
=
$field
;
$search_config_map
[
$field_list
[
$key
.
'_primary'
]
]
=
$field
;
}
else
{
$field_list
[
$key
]
=
$alias
.
'.'
.
$exploded
[
1
];
$search_config_map
[
$field_list
[
$key
]
]
=
$field
;
}
$join_clause
=
str_replace
(
'{ForeignTable}'
,
$alias
,
$search_config
[
$field
][
'JoinClause'
]);
$join_clause
=
str_replace
(
'{LocalTable}'
,
$items_table
,
$join_clause
);
$join_clauses
[]
=
' LEFT JOIN '
.
$foreign_table
.
' '
.
$alias
.
'
ON '
.
$join_clause
;
}
}
else
{
// processing fields from local table
if
(
$search_config
[
$field
][
'CustomFieldId'
])
{
$local_table
=
'custom_data'
;
// search by custom field value on current language
$custom_field_id
=
array_search
(
$field_list
[
$key
],
$custom_fields
);
$field_list
[
$key
]
=
'l'
.
$lang
.
'_cust_'
.
$custom_field_id
;
// search by custom field value on primary language
$field_list
[
$key
.
'_primary'
]
=
$local_table
.
'.l'
.
$this
->
Application
->
GetDefaultLanguageId
().
'_cust_'
.
$custom_field_id
;
$search_config_map
[
$field_list
[
$key
.
'_primary'
]
]
=
$field
;
}
$field_list
[
$key
]
=
$local_table
.
'.'
.
$field_list
[
$key
];
$search_config_map
[
$field_list
[
$key
]
]
=
$field
;
}
}
// keyword string processing
$search_helper
=&
$this
->
Application
->
recallObject
(
'SearchHelper'
);
/* @var $search_helper kSearchHelper */
$where_clause
=
Array
();
foreach
(
$field_list
as
$field
)
{
if
(
preg_match
(
'/^'
.
preg_quote
(
$items_table
,
'/'
)
.
'
\.
(.*)/'
,
$field
,
$regs
))
{
// local real field
$filter_data
=
$search_helper
->
getSearchClause
(
$object
,
$regs
[
1
],
$keywords
,
false
);
if
(
$filter_data
)
{
$where_clause
[]
=
$filter_data
[
'value'
];
}
}
elseif
(
preg_match
(
'/^custom_data
\.
(.*)/'
,
$field
,
$regs
))
{
$custom_field_name
=
'cust_'
.
$search_config_map
[
$field
];
$filter_data
=
$search_helper
->
getSearchClause
(
$object
,
$custom_field_name
,
$keywords
,
false
);
if
(
$filter_data
)
{
$where_clause
[]
=
str_replace
(
'`'
.
$custom_field_name
.
'`'
,
$field
,
$filter_data
[
'value'
]);
}
}
else
{
$where_clause
[]
=
$search_helper
->
buildWhereClause
(
$keywords
,
Array
(
$field
));
}
}
$where_clause
=
'(('
.
implode
(
') OR ('
,
$where_clause
)
.
'))'
;
// 2 braces for next clauses, see below!
$search_scope
=
$this
->
Application
->
GetVar
(
'search_scope'
);
if
(
$search_scope
==
'category'
)
{
$category_id
=
$this
->
Application
->
GetVar
(
'm_cat_id'
);
$category_filter
=
$this
->
getCategoryLimitClause
(
$category_id
);
if
(
$category_filter
!==
false
)
{
$join_clauses
[]
=
' LEFT JOIN '
.
TABLE_PREFIX
.
'CategoryItems ON '
.
TABLE_PREFIX
.
'CategoryItems.ItemResourceId = '
.
$items_table
.
'.ResourceId'
;
$join_clauses
[]
=
' LEFT JOIN '
.
TABLE_PREFIX
.
'Category ON '
.
TABLE_PREFIX
.
'Category.CategoryId = '
.
TABLE_PREFIX
.
'CategoryItems.CategoryId'
;
$where_clause
=
'('
.
$this
->
getCategoryLimitClause
(
$category_id
).
') AND '
.
$where_clause
;
}
}
$where_clause
=
$where_clause
.
' AND ('
.
$items_table
.
'.Status = '
.
STATUS_ACTIVE
.
')'
;
if
(
$event
->
MasterEvent
&&
$event
->
MasterEvent
->
Name
==
'OnListBuild'
)
{
if
(
$event
->
MasterEvent
->
getEventParam
(
'ResultIds'
))
{
$where_clause
.=
' AND '
.
$items_table
.
'.ResourceId IN ('
.
implode
(
','
,
$event
->
MasterEvent
->
getEventParam
(
'ResultIds'
)).
')'
;
}
}
// making relevance clause
$positive_words
=
$search_helper
->
getPositiveKeywords
(
$keywords
);
$this
->
Application
->
StoreVar
(
'highlight_keywords'
,
serialize
(
$positive_words
));
$revelance_parts
=
Array
();
reset
(
$search_config
);
foreach
(
$positive_words
as
$keyword_index
=>
$positive_word
)
{
$positive_word
=
$search_helper
->
transformWildcards
(
$positive_word
);
$positive_words
[
$keyword_index
]
=
$this
->
Conn
->
escape
(
$positive_word
);
}
foreach
(
$field_list
as
$field
)
{
if
(!
array_key_exists
(
$field
,
$search_config_map
))
{
$map_key
=
$search_config_map
[
$items_table
.
'.'
.
$field
];
}
else
{
$map_key
=
$search_config_map
[
$field
];
}
$config_elem
=
$search_config
[
$map_key
];
$weight
=
$config_elem
[
'Priority'
];
// search by whole words only ([[:<:]] - word boundary)
/*$revelance_parts[] = 'IF('.$field.' REGEXP "[[:<:]]('.implode(' ', $positive_words).')[[:>:]]", '.$weight.', 0)';
foreach ($positive_words as $keyword) {
$revelance_parts[] = 'IF('.$field.' REGEXP "[[:<:]]('.$keyword.')[[:>:]]", '.$weight.', 0)';
}*/
// search by partial word matches too
$revelance_parts
[]
=
'IF('
.
$field
.
' LIKE "%'
.
implode
(
' '
,
$positive_words
).
'%", '
.
$weight_sum
.
', 0)'
;
foreach
(
$positive_words
as
$keyword
)
{
$revelance_parts
[]
=
'IF('
.
$field
.
' LIKE "%'
.
$keyword
.
'%", '
.
$weight
.
', 0)'
;
}
}
$revelance_parts
=
array_unique
(
$revelance_parts
);
$conf_postfix
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'SearchConfigPostfix'
);
$rel_keywords
=
$this
->
Application
->
ConfigValue
(
'SearchRel_Keyword_'
.
$conf_postfix
)
/
100
;
$rel_pop
=
$this
->
Application
->
ConfigValue
(
'SearchRel_Pop_'
.
$conf_postfix
)
/
100
;
$rel_rating
=
$this
->
Application
->
ConfigValue
(
'SearchRel_Rating_'
.
$conf_postfix
)
/
100
;
$relevance_clause
=
'('
.
implode
(
' + '
,
$revelance_parts
).
') / '
.
$weight_sum
.
' * '
.
$rel_keywords
;
if
(
$rel_pop
&&
isset
(
$object
->
Fields
[
'Hits'
]))
{
$relevance_clause
.=
' + (Hits + 1) / (MAX(Hits) + 1) * '
.
$rel_pop
;
}
if
(
$rel_rating
&&
isset
(
$object
->
Fields
[
'CachedRating'
]))
{
$relevance_clause
.=
' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '
.
$rel_rating
;
}
// building final search query
if
(!
$this
->
Application
->
GetVar
(
'do_not_drop_search_table'
))
{
$this
->
Conn
->
Query
(
'DROP TABLE IF EXISTS '
.
$search_table
);
// erase old search table if clean k4 event
$this
->
Application
->
SetVar
(
'do_not_drop_search_table'
,
true
);
}
$search_table_exists
=
$this
->
Conn
->
Query
(
'SHOW TABLES LIKE "'
.
$search_table
.
'"'
);
if
(
$search_table_exists
)
{
$select_intro
=
'INSERT INTO '
.
$search_table
.
' (Relevance, ItemId, ResourceId, ItemType, EdPick) '
;
}
else
{
$select_intro
=
'CREATE TABLE '
.
$search_table
.
' AS '
;
}
$edpick_clause
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
.
'.EditorsPick'
,
'Fields'
)
?
$items_table
.
'.EditorsPick'
:
'0'
;
$sql
=
$select_intro
.
' SELECT '
.
$relevance_clause
.
' AS Relevance,
'
.
$items_table
.
'.'
.
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'IDField'
).
' AS ItemId,
'
.
$items_table
.
'.ResourceId,
'
.
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ItemType'
).
' AS ItemType,
'
.
$edpick_clause
.
' AS EdPick
FROM '
.
$object
->
TableName
.
'
'
.
implode
(
' '
,
$join_clauses
).
'
WHERE '
.
$where_clause
.
'
GROUP BY '
.
$items_table
.
'.'
.
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'IDField'
).
' ORDER BY Relevance DESC'
;
$res
=
$this
->
Conn
->
Query
(
$sql
);
if
(
!
$search_table_exists
)
{
$sql
=
'ALTER TABLE '
.
$search_table
.
'
ADD INDEX (ResourceId),
ADD INDEX (Relevance)'
;
$this
->
Conn
->
Query
(
$sql
);
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function
OnSubSearch
(&
$event
)
{
$search_table
=
TABLE_PREFIX
.
'ses_'
.
$this
->
Application
->
GetSID
().
'_'
.
TABLE_PREFIX
.
'Search'
;
$sql
=
'SHOW TABLES LIKE "'
.
$search_table
.
'"'
;
if
(
$this
->
Conn
->
Query
(
$sql
))
{
$sql
=
'SELECT DISTINCT ResourceId FROM '
.
$search_table
;
$ids
=
$this
->
Conn
->
GetCol
(
$sql
);
}
$event
->
setEventParam
(
'ResultIds'
,
$ids
);
$event
->
CallSubEvent
(
'OnSimpleSearch'
);
}
/**
* Enter description here...
*
* @param kEvent $event
* @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!!
*/
function
OnAdvancedSearch
(&
$event
)
{
$query_object
=&
$this
->
Application
->
recallObject
(
'HTTPQuery'
);
if
(!
isset
(
$query_object
->
Post
[
'andor'
]))
{
return
;
// used when navigating by pages or changing sorting in search results
}
$this
->
Application
->
RemoveVar
(
'keywords'
);
$this
->
Application
->
RemoveVar
(
'Search_Keywords'
);
$module_name
=
$this
->
Application
->
findModule
(
'Var'
,
$event
->
Prefix
,
'Name'
);
$sql
=
'SELECT *
FROM '
.
$this
->
Application
->
getUnitOption
(
'confs'
,
'TableName'
).
'
WHERE (ModuleName = '
.
$this
->
Conn
->
qstr
(
$module_name
).
') AND (AdvancedSearch = 1)'
;
$search_config
=
$this
->
Conn
->
Query
(
$sql
);
$lang
=
$this
->
Application
->
GetVar
(
'm_lang'
);
$object
=&
$event
->
getObject
();
$object
->
SetPage
(
1
);
$items_table
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'TableName'
);
$search_keywords
=
$this
->
Application
->
GetVar
(
'value'
);
// will not be changed
$keywords
=
$this
->
Application
->
GetVar
(
'value'
);
// will be changed down there
$verbs
=
$this
->
Application
->
GetVar
(
'verb'
);
$glues
=
$this
->
Application
->
GetVar
(
'andor'
);
$and_conditions
=
Array
();
$or_conditions
=
Array
();
$and_having_conditions
=
Array
();
$or_having_conditions
=
Array
();
$join_clauses
=
Array
();
$highlight_keywords
=
Array
();
$relevance_parts
=
Array
();
$alias_counter
=
0
;
$custom_fields
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'CustomFields'
);
if
(
$custom_fields
)
{
$custom_table
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
.
'-cdata'
,
'TableName'
);
$join_clauses
[]
=
' LEFT JOIN '
.
$custom_table
.
' custom_data ON '
.
$items_table
.
'.ResourceId = custom_data.ResourceId'
;
}
$search_log
=
''
;
$weight_sum
=
0
;
// processing fields and preparing conditions
foreach
(
$search_config
as
$record
)
{
$field
=
$record
[
'FieldName'
];
$join_clause
=
''
;
$condition_mode
=
'WHERE'
;
// field processing
$options
=
$object
->
getFieldOptions
(
$field
);
$local_table
=
TABLE_PREFIX
.
$record
[
'TableName'
];
$weight_sum
+=
$record
[
'Priority'
];
// counting weight sum; used when making relevance clause
// processing multilingual fields
if
(
getArrayValue
(
$options
,
'formatter'
)
==
'kMultiLanguage'
)
{
$field_name
=
'l'
.
$lang
.
'_'
.
$field
;
}
else
{
$field_name
=
$field
;
}
// processing fields from other tables
if
(
$foreign_field
=
$record
[
'ForeignField'
])
{
$exploded
=
explode
(
':'
,
$foreign_field
,
2
);
if
(
$exploded
[
0
]
==
'CALC'
)
{
$user_groups
=
$this
->
Application
->
RecallVar
(
'UserGroups'
);
$field_name
=
str_replace
(
'{PREFIX}'
,
TABLE_PREFIX
,
$exploded
[
1
]);
$join_clause
=
str_replace
(
'{PREFIX}'
,
TABLE_PREFIX
,
$record
[
'JoinClause'
]);
$join_clause
=
str_replace
(
'{USER_GROUPS}'
,
$user_groups
,
$join_clause
);
$join_clause
=
' LEFT JOIN '
.
$join_clause
;
$condition_mode
=
'HAVING'
;
}
else
{
$exploded
=
explode
(
'.'
,
$foreign_field
);
$foreign_table
=
TABLE_PREFIX
.
$exploded
[
0
];
if
(
$record
[
'CustomFieldId'
])
{
$exploded
[
1
]
=
'l'
.
$lang
.
'_'
.
$exploded
[
1
];
}
$alias_counter
++;
$alias
=
't'
.
$alias_counter
;
$field_name
=
$alias
.
'.'
.
$exploded
[
1
];
$join_clause
=
str_replace
(
'{ForeignTable}'
,
$alias
,
$record
[
'JoinClause'
]);
$join_clause
=
str_replace
(
'{LocalTable}'
,
$items_table
,
$join_clause
);
if
(
$record
[
'CustomFieldId'
])
{
$join_clause
.=
' AND '
.
$alias
.
'.CustomFieldId='
.
$record
[
'CustomFieldId'
];
}
$join_clause
=
' LEFT JOIN '
.
$foreign_table
.
' '
.
$alias
.
'
ON '
.
$join_clause
;
}
}
else
{
// processing fields from local table
if
(
$record
[
'CustomFieldId'
])
{
$local_table
=
'custom_data'
;
$field_name
=
'l'
.
$lang
.
'_cust_'
.
array_search
(
$field_name
,
$custom_fields
);
}
$field_name
=
$local_table
.
'.'
.
$field_name
;
}
$condition
=
$this
->
getAdvancedSearchCondition
(
$field_name
,
$record
,
$keywords
,
$verbs
,
$highlight_keywords
);
if
(
$record
[
'CustomFieldId'
]
&&
strlen
(
$condition
))
{
// search in primary value of custom field + value in current language
$field_name
=
$local_table
.
'.'
.
'l'
.
$this
->
Application
->
GetDefaultLanguageId
().
'_cust_'
.
array_search
(
$field
,
$custom_fields
);
$primary_condition
=
$this
->
getAdvancedSearchCondition
(
$field_name
,
$record
,
$keywords
,
$verbs
,
$highlight_keywords
);
$condition
=
'('
.
$condition
.
' OR '
.
$primary_condition
.
')'
;
}
if
(
$condition
)
{
if
(
$join_clause
)
{
$join_clauses
[]
=
$join_clause
;
}
$relevance_parts
[]
=
'IF('
.
$condition
.
', '
.
$record
[
'Priority'
].
', 0)'
;
if
(
$glues
[
$field
]
==
1
)
{
// and
if
(
$condition_mode
==
'WHERE'
)
{
$and_conditions
[]
=
$condition
;
}
else
{
$and_having_conditions
[]
=
$condition
;
}
}
else
{
// or
if
(
$condition_mode
==
'WHERE'
)
{
$or_conditions
[]
=
$condition
;
}
else
{
$or_having_conditions
[]
=
$condition
;
}
}
// create search log record
$search_log_data
=
Array
(
'search_config'
=>
$record
,
'verb'
=>
getArrayValue
(
$verbs
,
$field
),
'value'
=>
(
$record
[
'FieldType'
]
==
'range'
)
?
$search_keywords
[
$field
.
'_from'
].
'|'
.
$search_keywords
[
$field
.
'_to'
]
:
$search_keywords
[
$field
]);
$search_log
[]
=
$this
->
Application
->
Phrase
(
'la_Field'
).
' "'
.
$this
->
getHuman
(
'Field'
,
$search_log_data
).
'" '
.
$this
->
getHuman
(
'Verb'
,
$search_log_data
).
' '
.
$this
->
Application
->
Phrase
(
'la_Value'
).
' '
.
$this
->
getHuman
(
'Value'
,
$search_log_data
).
' '
.
$this
->
Application
->
Phrase
(
$glues
[
$field
]
==
1
?
'lu_And'
:
'lu_Or'
);
}
}
if
(
$search_log
)
{
$search_log
=
implode
(
'<br />'
,
$search_log
);
$search_log
=
preg_replace
(
'/(.*) '
.
preg_quote
(
$this
->
Application
->
Phrase
(
'lu_and'
),
'/'
).
'|'
.
preg_quote
(
$this
->
Application
->
Phrase
(
'lu_or'
),
'/'
).
'$/is'
,
'
\\
1'
,
$search_log
);
$this
->
saveToSearchLog
(
$search_log
,
1
);
// advanced search
}
$this
->
Application
->
StoreVar
(
'highlight_keywords'
,
serialize
(
$highlight_keywords
));
// making relevance clause
if
(
$relevance_parts
)
{
$conf_postfix
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'SearchConfigPostfix'
);
$rel_keywords
=
$this
->
Application
->
ConfigValue
(
'SearchRel_Keyword_'
.
$conf_postfix
)
/
100
;
$rel_pop
=
$this
->
Application
->
ConfigValue
(
'SearchRel_Pop_'
.
$conf_postfix
)
/
100
;
$rel_rating
=
$this
->
Application
->
ConfigValue
(
'SearchRel_Rating_'
.
$conf_postfix
)
/
100
;
$relevance_clause
=
'('
.
implode
(
' + '
,
$relevance_parts
).
') / '
.
$weight_sum
.
' * '
.
$rel_keywords
;
$relevance_clause
.=
' + (Hits + 1) / (MAX(Hits) + 1) * '
.
$rel_pop
;
$relevance_clause
.=
' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '
.
$rel_rating
;
}
else
{
$relevance_clause
=
'0'
;
}
// building having clause
if
(
$or_having_conditions
)
{
$and_having_conditions
[]
=
'('
.
implode
(
' OR '
,
$or_having_conditions
).
')'
;
}
$having_clause
=
implode
(
' AND '
,
$and_having_conditions
);
$having_clause
=
$having_clause
?
' HAVING '
.
$having_clause
:
''
;
// building where clause
if
(
$or_conditions
)
{
$and_conditions
[]
=
'('
.
implode
(
' OR '
,
$or_conditions
).
')'
;
}
// $and_conditions[] = $items_table.'.Status = 1';
$where_clause
=
implode
(
' AND '
,
$and_conditions
);
if
(!
$where_clause
)
{
if
(
$having_clause
)
{
$where_clause
=
'1'
;
}
else
{
$where_clause
=
'0'
;
$this
->
Application
->
SetVar
(
'adv_search_error'
,
1
);
}
}
$where_clause
.=
' AND '
.
$items_table
.
'.Status = 1'
;
// building final search query
$search_table
=
TABLE_PREFIX
.
'ses_'
.
$this
->
Application
->
GetSID
().
'_'
.
TABLE_PREFIX
.
'Search'
;
$this
->
Conn
->
Query
(
'DROP TABLE IF EXISTS '
.
$search_table
);
$id_field
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'IDField'
);
$fields
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'Fields'
);
$pick_field
=
isset
(
$fields
[
'EditorsPick'
])
?
$items_table
.
'.EditorsPick'
:
'0'
;
$sql
=
' CREATE TABLE '
.
$search_table
.
'
SELECT '
.
$relevance_clause
.
' AS Relevance,
'
.
$items_table
.
'.'
.
$id_field
.
' AS ItemId,
'
.
$items_table
.
'.ResourceId AS ResourceId,
11 AS ItemType,
'
.
$pick_field
.
' AS EdPick
FROM '
.
$items_table
.
'
'
.
implode
(
' '
,
$join_clauses
).
'
WHERE '
.
$where_clause
.
'
GROUP BY '
.
$items_table
.
'.'
.
$id_field
.
$having_clause
;
$res
=
$this
->
Conn
->
Query
(
$sql
);
}
function
getAdvancedSearchCondition
(
$field_name
,
$record
,
$keywords
,
$verbs
,
&
$highlight_keywords
)
{
$field
=
$record
[
'FieldName'
];
$condition_patterns
=
Array
(
'any'
=>
'%s LIKE %s'
,
'contains'
=>
'%s LIKE %s'
,
'notcontains'
=>
'(NOT (%1$s LIKE %2$s) OR %1$s IS NULL)'
,
'is'
=>
'%s = %s'
,
'isnot'
=>
'(%1$s != %2$s OR %1$s IS NULL)'
);
$condition
=
''
;
switch
(
$record
[
'FieldType'
])
{
case
'select'
:
$keywords
[
$field
]
=
unhtmlentities
(
$keywords
[
$field
]
);
if
(
$keywords
[
$field
])
{
$condition
=
sprintf
(
$condition_patterns
[
'is'
],
$field_name
,
$this
->
Conn
->
qstr
(
$keywords
[
$field
]
));
}
break
;
case
'multiselect'
:
$keywords
[
$field
]
=
unhtmlentities
(
$keywords
[
$field
]
);
if
(
$keywords
[
$field
])
{
$condition
=
Array
();
$values
=
explode
(
'|'
,
substr
(
$keywords
[
$field
],
1
,
-
1
));
foreach
(
$values
as
$selected_value
)
{
$condition
[]
=
sprintf
(
$condition_patterns
[
'contains'
],
$field_name
,
$this
->
Conn
->
qstr
(
'%|'
.
$selected_value
.
'|%'
));
}
$condition
=
'('
.
implode
(
' OR '
,
$condition
).
')'
;
}
break
;
case
'text'
:
$keywords
[
$field
]
=
unhtmlentities
(
$keywords
[
$field
]
);
if
(
mb_strlen
(
$keywords
[
$field
])
>=
$this
->
Application
->
ConfigValue
(
'Search_MinKeyword_Length'
))
{
$highlight_keywords
[]
=
$keywords
[
$field
];
if
(
in_array
(
$verbs
[
$field
],
Array
(
'any'
,
'contains'
,
'notcontains'
)))
{
$keywords
[
$field
]
=
'%'
.
strtr
(
$keywords
[
$field
],
Array
(
'%'
=>
'
\\
%'
,
'_'
=>
'
\\
_'
)).
'%'
;
}
$condition
=
sprintf
(
$condition_patterns
[
$verbs
[
$field
]],
$field_name
,
$this
->
Conn
->
qstr
(
$keywords
[
$field
]
));
}
break
;
case
'boolean'
:
if
(
$keywords
[
$field
]
!=
-
1
)
{
$property_mappings
=
$this
->
Application
->
getUnitOption
(
$this
->
Prefix
,
'ItemPropertyMappings'
);
$items_table
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'TableName'
);
switch
(
$field
)
{
case
'HotItem'
:
$hot_limit_var
=
getArrayValue
(
$property_mappings
,
'HotLimit'
);
if
(
$hot_limit_var
)
{
$hot_limit
=
(
int
)
$this
->
Application
->
getDBCache
(
$hot_limit_var
);
$condition
=
'IF('
.
$items_table
.
'.HotItem = 2,
IF('
.
$items_table
.
'.Hits >= '
.
$hot_limit
.
', 1, 0), '
.
$items_table
.
'.HotItem) = '
.
$keywords
[
$field
];
}
break
;
case
'PopItem'
:
$votes2pop_var
=
getArrayValue
(
$property_mappings
,
'VotesToPop'
);
$rating2pop_var
=
getArrayValue
(
$property_mappings
,
'RatingToPop'
);
if
(
$votes2pop_var
&&
$rating2pop_var
)
{
$condition
=
'IF('
.
$items_table
.
'.PopItem = 2, IF('
.
$items_table
.
'.CachedVotesQty >= '
.
$this
->
Application
->
ConfigValue
(
$votes2pop_var
).
' AND '
.
$items_table
.
'.CachedRating >= '
.
$this
->
Application
->
ConfigValue
(
$rating2pop_var
).
', 1, 0), '
.
$items_table
.
'.PopItem) = '
.
$keywords
[
$field
];
}
break
;
case
'NewItem'
:
$new_days_var
=
getArrayValue
(
$property_mappings
,
'NewDays'
);
if
(
$new_days_var
)
{
$condition
=
'IF('
.
$items_table
.
'.NewItem = 2,
IF('
.
$items_table
.
'.CreatedOn >= (UNIX_TIMESTAMP() - '
.
$this
->
Application
->
ConfigValue
(
$new_days_var
).
'*3600*24), 1, 0), '
.
$items_table
.
'.NewItem) = '
.
$keywords
[
$field
];
}
break
;
case
'EditorsPick'
:
$condition
=
$items_table
.
'.EditorsPick = '
.
$keywords
[
$field
];
break
;
}
}
break
;
case
'range'
:
$range_conditions
=
Array
();
if
(
$keywords
[
$field
.
'_from'
]
&&
!
preg_match
(
"/[^0-9]/i"
,
$keywords
[
$field
.
'_from'
]))
{
$range_conditions
[]
=
$field_name
.
' >= '
.
$keywords
[
$field
.
'_from'
];
}
if
(
$keywords
[
$field
.
'_to'
]
&&
!
preg_match
(
"/[^0-9]/i"
,
$keywords
[
$field
.
'_to'
]))
{
$range_conditions
[]
=
$field_name
.
' <= '
.
$keywords
[
$field
.
'_to'
];
}
if
(
$range_conditions
)
{
$condition
=
implode
(
' AND '
,
$range_conditions
);
}
break
;
case
'date'
:
if
(
$keywords
[
$field
])
{
if
(
in_array
(
$keywords
[
$field
],
Array
(
'today'
,
'yesterday'
)))
{
$current_time
=
getdate
();
$day_begin
=
adodb_mktime
(
0
,
0
,
0
,
$current_time
[
'mon'
],
$current_time
[
'mday'
],
$current_time
[
'year'
]);
$time_mapping
=
Array
(
'today'
=>
$day_begin
,
'yesterday'
=>
(
$day_begin
-
86400
));
$min_time
=
$time_mapping
[
$keywords
[
$field
]];
}
else
{
$time_mapping
=
Array
(
'last_week'
=>
604800
,
'last_month'
=>
2628000
,
'last_3_months'
=>
7884000
,
'last_6_months'
=>
15768000
,
'last_year'
=>
31536000
,
);
$min_time
=
adodb_mktime
()
-
$time_mapping
[
$keywords
[
$field
]];
}
$condition
=
$field_name
.
' > '
.
$min_time
;
}
break
;
}
return
$condition
;
}
function
getHuman
(
$type
,
$search_data
)
{
$type
=
ucfirst
(
strtolower
(
$type
));
extract
(
$search_data
);
switch
(
$type
)
{
case
'Field'
:
return
$this
->
Application
->
Phrase
(
$search_config
[
'DisplayName'
]);
break
;
case
'Verb'
:
return
$verb
?
$this
->
Application
->
Phrase
(
'lu_advsearch_'
.
$verb
)
:
''
;
break
;
case
'Value'
:
switch
(
$search_config
[
'FieldType'
])
{
case
'date'
:
$values
=
Array
(
0
=>
'lu_comm_Any'
,
'today'
=>
'lu_comm_Today'
,
'yesterday'
=>
'lu_comm_Yesterday'
,
'last_week'
=>
'lu_comm_LastWeek'
,
'last_month'
=>
'lu_comm_LastMonth'
,
'last_3_months'
=>
'lu_comm_Last3Months'
,
'last_6_months'
=>
'lu_comm_Last6Months'
,
'last_year'
=>
'lu_comm_LastYear'
);
$ret
=
$this
->
Application
->
Phrase
(
$values
[
$value
]);
break
;
case
'range'
:
$value
=
explode
(
'|'
,
$value
);
return
$this
->
Application
->
Phrase
(
'lu_comm_From'
).
' "'
.
$value
[
0
].
'" '
.
$this
->
Application
->
Phrase
(
'lu_comm_To'
).
' "'
.
$value
[
1
].
'"'
;
break
;
case
'boolean'
:
$values
=
Array
(
1
=>
'lu_comm_Yes'
,
0
=>
'lu_comm_No'
,
-
1
=>
'lu_comm_Both'
);
$ret
=
$this
->
Application
->
Phrase
(
$values
[
$value
]);
break
;
default
:
$ret
=
$value
;
break
;
}
return
'"'
.
$ret
.
'"'
;
break
;
}
}
/**
* Set's correct page for list
* based on data provided with event
*
* @param kEvent $event
* @access private
* @see OnListBuild
*/
function
SetPagination
(&
$event
)
{
$object
=&
$event
->
getObject
();
/* @var $object kDBList */
// get PerPage (forced -> session -> config -> 10)
$object
->
SetPerPage
(
$this
->
getPerPage
(
$event
)
);
// main lists on Front-End have special get parameter for page
$page
=
$object
->
mainList
?
$this
->
Application
->
GetVar
(
'page'
)
:
false
;
if
(!
$page
)
{
// page is given in "env" variable for given prefix
$page
=
$this
->
Application
->
GetVar
(
$event
->
getPrefixSpecial
()
.
'_Page'
);
}
if
(!
$page
&&
$event
->
Special
)
{
// when not part of env, then variables like "prefix.special_Page" are
// replaced (by PHP) with "prefix_special_Page", so check for that too
$page
=
$this
->
Application
->
GetVar
(
$event
->
getPrefixSpecial
(
true
)
.
'_Page'
);
}
if
(!
$object
->
mainList
)
{
// main lists doesn't use session for page storing
$this
->
Application
->
StoreVarDefault
(
$event
->
getPrefixSpecial
()
.
'_Page'
,
1
,
true
);
// true for optional
if
(!
$page
)
{
if
(
$this
->
Application
->
RewriteURLs
())
{
// when page not found by prefix+special, then try to search it without special at all
$page
=
$this
->
Application
->
GetVar
(
$event
->
Prefix
.
'_Page'
);
if
(!
$page
)
{
// page not found in request -> get from session
$page
=
$this
->
Application
->
RecallVar
(
$event
->
Prefix
.
'_Page'
);
}
if
(
$page
)
{
// page found in request -> store in session
$this
->
Application
->
StoreVar
(
$event
->
getPrefixSpecial
()
.
'_Page'
,
$page
,
true
);
//true for optional
}
}
else
{
// page not found in request -> get from session
$page
=
$this
->
Application
->
RecallVar
(
$event
->
getPrefixSpecial
()
.
'_Page'
);
}
}
else
{
// page found in request -> store in session
$this
->
Application
->
StoreVar
(
$event
->
getPrefixSpecial
()
.
'_Page'
,
$page
,
true
);
//true for optional
}
if
(
!
$event
->
getEventParam
(
'skip_counting'
)
)
{
// when stored page is larger, then maximal list page number
// (such case is also processed in kDBList::Query method)
$pages
=
$object
->
GetTotalPages
();
if
(
$page
>
$pages
)
{
$page
=
1
;
$this
->
Application
->
StoreVar
(
$event
->
getPrefixSpecial
().
'_Page'
,
1
,
true
);
}
}
}
$object
->
SetPage
(
$page
);
}
/* === RELATED TO IMPORT/EXPORT: BEGIN === */
/**
* Shows export dialog
*
* @param kEvent $event
*/
function
OnExport
(&
$event
)
{
$selected_ids
=
$this
->
StoreSelectedIDs
(
$event
);
if
(
implode
(
','
,
$selected_ids
)
==
''
)
{
// K4 fix when no ids found bad selected ids array is formed
$selected_ids
=
false
;
}
$selected_cats_ids
=
$this
->
Application
->
GetVar
(
'export_categories'
);
$this
->
Application
->
StoreVar
(
$event
->
Prefix
.
'_export_ids'
,
$selected_ids
?
implode
(
','
,
$selected_ids
)
:
''
);
$this
->
Application
->
StoreVar
(
$event
->
Prefix
.
'_export_cats_ids'
,
$selected_cats_ids
);
$export_helper
=&
$this
->
Application
->
recallObject
(
'CatItemExportHelper'
);
/* @var $export_helper kCatDBItemExportHelper */
$redirect_params
=
Array
(
$this
->
Prefix
.
'.export_event'
=>
'OnNew'
,
'pass'
=>
'all,'
.
$this
->
Prefix
.
'.export'
);
$event
->
setRedirectParams
(
$redirect_params
);
}
/**
* Performs each export step & displays progress percent
*
* @param kEvent $event
*/
function
OnExportProgress
(&
$event
)
{
$export_object
=&
$this
->
Application
->
recallObject
(
'CatItemExportHelper'
);
/* @var $export_object kCatDBItemExportHelper */
$event
=
new
kEvent
(
$event
->
getPrefixSpecial
().
':OnDummy'
);
$action_method
=
'perform'
.
ucfirst
(
$event
->
Special
);
$field_values
=
$export_object
->
$action_method
(
$event
);
// finish code is done from JS now
if
(
$field_values
[
'start_from'
]
==
$field_values
[
'total_records'
])
{
if
(
$event
->
Special
==
'import'
)
{
$this
->
Application
->
StoreVar
(
'PermCache_UpdateRequired'
,
1
);
$url_params
=
Array
(
't'
=>
'catalog/catalog'
,
'm_cat_id'
=>
$this
->
Application
->
RecallVar
(
'ImportCategory'
),
'anchor'
=>
'tab-'
.
$event
->
Prefix
,
);
$this
->
Application
->
EventManager
->
openerStackChange
(
$url_params
);
$event
->
SetRedirectParam
(
'opener'
,
'u'
);
}
elseif
(
$event
->
Special
==
'export'
)
{
$event
->
redirect
=
$export_object
->
getModuleName
(
$event
)
.
'/'
.
$event
->
Special
.
'_finish'
;
$event
->
SetRedirectParam
(
'pass'
,
'all'
);
}
return
;
}
$export_options
=
$export_object
->
loadOptions
(
$event
);
echo
$export_options
[
'start_from'
]
*
100
/
$export_options
[
'total_records'
];
$event
->
status
=
erSTOP
;
}
/**
* Returns specific to each item type columns only
*
* @param kEvent $event
* @return Array
*/
function
getCustomExportColumns
(&
$event
)
{
return
Array
(
'__VIRTUAL__ThumbnailImage'
=>
'ThumbnailImage'
,
'__VIRTUAL__FullImage'
=>
'FullImage'
,
'__VIRTUAL__ImageAlt'
=>
'ImageAlt'
);
}
/**
* Sets non standart virtual fields (e.g. to other tables)
*
* @param kEvent $event
*/
function
setCustomExportColumns
(&
$event
)
{
$this
->
restorePrimaryImage
(
$event
);
}
/**
* Create/Update primary image record in info found in imported data
*
* @param kEvent $event
*/
function
restorePrimaryImage
(&
$event
)
{
$object
=&
$event
->
getObject
();
$has_image_info
=
$object
->
GetDBField
(
'ImageAlt'
)
&&
(
$object
->
GetDBField
(
'ThumbnailImage'
)
||
$object
->
GetDBField
(
'FullImage'
));
if
(!
$has_image_info
)
{
return
false
;
}
$image_data
=
$object
->
getPrimaryImageData
();
$image
=&
$this
->
Application
->
recallObject
(
'img'
,
null
,
Array
(
'skip_autoload'
=>
true
));
if
(
$image_data
)
{
$image
->
Load
(
$image_data
[
'ImageId'
]);
}
else
{
$image
->
Clear
();
$image
->
SetDBField
(
'Name'
,
'main'
);
$image
->
SetDBField
(
'DefaultImg'
,
1
);
$image
->
SetDBField
(
'ResourceId'
,
$object
->
GetDBField
(
'ResourceId'
));
}
$image
->
SetDBField
(
'AltName'
,
$object
->
GetDBField
(
'ImageAlt'
));
if
(
$object
->
GetDBField
(
'ThumbnailImage'
))
{
$thumbnail_field
=
$this
->
isURL
(
$object
->
GetDBField
(
'ThumbnailImage'
)
)
?
'ThumbUrl'
:
'ThumbPath'
;
$image
->
SetDBField
(
$thumbnail_field
,
$object
->
GetDBField
(
'ThumbnailImage'
)
);
$image
->
SetDBField
(
'LocalThumb'
,
$thumbnail_field
==
'ThumbPath'
?
1
:
0
);
}
if
(!
$object
->
GetDBField
(
'FullImage'
))
{
$image
->
SetDBField
(
'SameImages'
,
1
);
}
else
{
$image
->
SetDBField
(
'SameImages'
,
0
);
$full_field
=
$this
->
isURL
(
$object
->
GetDBField
(
'FullImage'
)
)
?
'Url'
:
'LocalPath'
;
$image
->
SetDBField
(
$full_field
,
$object
->
GetDBField
(
'FullImage'
)
);
$image
->
SetDBField
(
'LocalImage'
,
$full_field
==
'LocalPath'
?
1
:
0
);
}
if
(
$image
->
isLoaded
())
{
$image
->
Update
();
}
else
{
$image
->
Create
();
}
}
function
isURL
(
$path
)
{
return
preg_match
(
'#(http|https)://(.*)#'
,
$path
);
}
/**
* Prepares item for import/export operations
*
* @param kEvent $event
*/
function
OnNew
(&
$event
)
{
parent
::
OnNew
(
$event
);
if
(
$event
->
Special
==
'import'
||
$event
->
Special
==
'export'
)
{
$export_helper
=&
$this
->
Application
->
recallObject
(
'CatItemExportHelper'
);
$export_helper
->
setRequiredFields
(
$event
);
}
}
/**
* Process items selected in item_selector
*
* @param kEvent $event
*/
function
OnProcessSelected
(&
$event
)
{
$selected_ids
=
$this
->
Application
->
GetVar
(
'selected_ids'
);
$dst_field
=
$this
->
Application
->
RecallVar
(
'dst_field'
);
if
(
$dst_field
==
'ItemCategory'
)
{
// Item Edit -> Categories Tab -> New Categories
$object
=&
$event
->
getObject
();
$category_ids
=
explode
(
','
,
$selected_ids
[
'c'
]);
foreach
(
$category_ids
as
$category_id
)
{
$object
->
assignToCategory
(
$category_id
);
}
}
if
(
$dst_field
==
'ImportCategory'
)
{
// Tools -> Import -> Item Import -> Select Import Category
$this
->
Application
->
StoreVar
(
'ImportCategory'
,
$selected_ids
[
'c'
]);
// $this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 1); // not to loose import/export values on form refresh
$url_params
=
Array
(
$event
->
getPrefixSpecial
()
.
'_id'
=>
0
,
$event
->
getPrefixSpecial
()
.
'_event'
=>
'OnExportBegin'
,
// 'm_opener' => 's',
);
$this
->
Application
->
EventManager
->
openerStackChange
(
$url_params
);
}
$event
->
SetRedirectParam
(
'opener'
,
'u'
);
}
/**
* Saves Import/Export settings to session
*
* @param kEvent $event
*/
function
OnSaveSettings
(&
$event
)
{
$event
->
redirect
=
false
;
$items_info
=
$this
->
Application
->
GetVar
(
$event
->
getPrefixSpecial
(
true
)
);
if
(
$items_info
)
{
list
(
$id
,
$field_values
)
=
each
(
$items_info
);
$object
=&
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
)
);
$object
->
SetFieldsFromHash
(
$field_values
);
$field_values
[
'ImportFilename'
]
=
$object
->
GetDBField
(
'ImportFilename'
);
//if upload formatter has renamed the file during moving !!!
$field_values
[
'ImportSource'
]
=
2
;
$field_values
[
'ImportLocalFilename'
]
=
$object
->
GetDBField
(
'ImportFilename'
);
$items_info
[
$id
]
=
$field_values
;
$this
->
Application
->
StoreVar
(
$event
->
getPrefixSpecial
().
'_ItemsInfo'
,
serialize
(
$items_info
));
}
}
/**
* Saves Import/Export settings to session
*
* @param kEvent $event
*/
function
OnResetSettings
(&
$event
)
{
$this
->
Application
->
StoreVar
(
'ImportCategory'
,
$this
->
Application
->
getBaseCategory
());
}
function
OnCancelAction
(&
$event
)
{
$event
->
redirect_params
=
Array
(
'pass'
=>
'all,'
.
$event
->
GetPrefixSpecial
());
$event
->
redirect
=
$this
->
Application
->
GetVar
(
'cancel_template'
);
}
/* === RELATED TO IMPORT/EXPORT: END === */
/**
* Stores item's owner login into separate field together with id
*
* @param kEvent $event
* @param string $id_field
* @param string $cached_field
*/
function
cacheItemOwner
(&
$event
,
$id_field
,
$cached_field
)
{
$object
=&
$event
->
getObject
();
$user_id
=
$object
->
GetDBField
(
$id_field
);
$options
=
$object
->
GetFieldOptions
(
$id_field
);
if
(
isset
(
$options
[
'options'
][
$user_id
]))
{
$object
->
SetDBField
(
$cached_field
,
$options
[
'options'
][
$user_id
]);
}
else
{
$id_field
=
$this
->
Application
->
getUnitOption
(
'u'
,
'IDField'
);
$table_name
=
$this
->
Application
->
getUnitOption
(
'u'
,
'TableName'
);
$sql
=
'SELECT Login
FROM '
.
$table_name
.
'
WHERE '
.
$id_field
.
' = '
.
$user_id
;
$object
->
SetDBField
(
$cached_field
,
$this
->
Conn
->
GetOne
(
$sql
));
}
}
/**
* Saves item beeing edited into temp table
*
* @param kEvent $event
*/
function
OnPreSave
(&
$event
)
{
parent
::
OnPreSave
(
$event
);
$use_pending_editing
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'UsePendingEditing'
);
if
(
$event
->
status
==
erSUCCESS
&&
$use_pending_editing
)
{
// decision: clone or not clone
$object
=&
$event
->
getObject
();
if
(
$object
->
GetID
()
==
0
||
$object
->
GetDBField
(
'OrgId'
)
>
0
)
{
// new items or cloned items shouldn't be cloned again
return
true
;
}
$perm_helper
=&
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
if
(
$perm_helper
->
ModifyCheckPermission
(
$object
->
GetDBField
(
$owner_field
),
$object
->
GetDBField
(
'CategoryId'
),
$event
->
Prefix
)
==
2
)
{
// 1. clone original item
$temp_handler
=&
$this
->
Application
->
recallObject
(
$event
->
getPrefixSpecial
().
'_TempHandler'
,
'kTempTablesHandler'
);
$cloned_ids
=
$temp_handler
->
CloneItems
(
$event
->
Prefix
,
$event
->
Special
,
Array
(
$object
->
GetID
()),
null
,
null
,
null
,
true
);
$ci_table
=
$this
->
Application
->
GetTempName
(
TABLE_PREFIX
.
'CategoryItems'
);
// 2. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
$sql
=
'SELECT ResourceId
FROM '
.
$object
->
TableName
.
'
WHERE '
.
$object
->
IDField
.
' = '
.
$cloned_ids
[
0
];
$clone_resource_id
=
$this
->
Conn
->
GetOne
(
$sql
);
$sql
=
'DELETE FROM '
.
$ci_table
.
'
WHERE ItemResourceId = '
.
$clone_resource_id
.
' AND PrimaryCat = 1'
;
$this
->
Conn
->
Query
(
$sql
);
// 3. copy main item categoryitems to cloned item
$sql
=
' INSERT INTO '
.
$ci_table
.
' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
SELECT CategoryId, '
.
$clone_resource_id
.
' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
FROM '
.
$ci_table
.
'
WHERE ItemResourceId = '
.
$object
->
GetDBField
(
'ResourceId'
);
$this
->
Conn
->
Query
(
$sql
);
// 4. put cloned id to OrgId field of item being cloned
$sql
=
'UPDATE '
.
$object
->
TableName
.
'
SET OrgId = '
.
$object
->
GetID
().
'
WHERE '
.
$object
->
IDField
.
' = '
.
$cloned_ids
[
0
];
$this
->
Conn
->
Query
(
$sql
);
// 5. substitute id of item being cloned with clone id
$this
->
Application
->
SetVar
(
$event
->
getPrefixSpecial
().
'_id'
,
$cloned_ids
[
0
]);
$selected_ids
=
$this
->
getSelectedIDs
(
$event
,
true
);
$selected_ids
[
array_search
(
$object
->
GetID
(),
$selected_ids
)
]
=
$cloned_ids
[
0
];
$this
->
StoreSelectedIDs
(
$event
,
$selected_ids
);
// 6. delete original item from temp table
$temp_handler
->
DeleteItems
(
$event
->
Prefix
,
$event
->
Special
,
Array
(
$object
->
GetID
()));
}
}
}
/**
* Sets default expiration based on module setting
*
* @param kEvent $event
*/
function
OnPreCreate
(&
$event
)
{
parent
::
OnPreCreate
(
$event
);
if
(
$event
->
status
==
erSUCCESS
)
{
$object
=&
$event
->
getObject
();
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
$object
->
SetDBField
(
$owner_field
,
$this
->
Application
->
RecallVar
(
'user_id'
));
}
}
/**
* Occures before original item of item in pending editing got deleted (for hooking only)
*
* @param kEvent $event
*/
function
OnBeforeDeleteOriginal
(&
$event
)
{
}
/**
* Occures before an item is cloneded
* Id of ORIGINAL item is passed as event' 'id' param
* Do not call object' Update method in this event, just set needed fields!
*
* @param kEvent $event
*/
function
OnBeforeClone
(&
$event
)
{
if
(
$this
->
Application
->
GetVar
(
'ResetCatBeforeClone'
))
{
$object
=&
$event
->
getObject
();
$object
->
SetDBField
(
'CategoryId'
,
null
);
}
}
/**
* Set status for new category item based on user permission in category
*
* @param kEvent $event
*/
function
OnBeforeItemCreate
(&
$event
)
{
$object
=&
$event
->
getObject
();
/* @var $object kDBItem */
$is_admin
=
$this
->
Application
->
isAdminUser
;
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
if
((!
$object
->
IsTempTable
()
&&
!
$is_admin
)
||
(
$is_admin
&&
!
$object
->
GetDBField
(
$owner_field
)))
{
// Front-end OR owner not specified -> set to currently logged-in user
$object
->
SetDBField
(
$owner_field
,
$this
->
Application
->
RecallVar
(
'user_id'
));
}
if
(
$object
->
Validate
()
)
{
$object
->
SetDBField
(
'ResourceId'
,
$this
->
Application
->
NextResourceId
());
}
if
(!
$this
->
Application
->
isAdmin
)
{
$this
->
setItemStatusByPermission
(
$event
);
}
}
/**
* Sets category item status based on user permissions (only on Front-end)
*
* @param kEvent $event
*/
function
setItemStatusByPermission
(&
$event
)
{
$use_pending_editing
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'UsePendingEditing'
);
if
(!
$use_pending_editing
)
{
return
;
}
$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
)
{
$event
->
status
=
erFAIL
;
}
else
{
$object
->
SetDBField
(
'Status'
,
$item_status
);
}
}
/**
* Creates category item & redirects to confirmation template (front-end only)
*
* @param kEvent $event
*/
function
OnCreate
(&
$event
)
{
parent
::
OnCreate
(
$event
);
$this
->
SetFrontRedirectTemplate
(
$event
,
'suggest'
);
}
/**
* Returns item's categories (allows to exclude primary category)
*
* @param int $resource_id
* @param bool $with_primary
* @return Array
*/
function
getItemCategories
(
$resource_id
,
$with_primary
=
false
)
{
$sql
=
'SELECT CategoryId
FROM '
.
TABLE_PREFIX
.
'CategoryItems
WHERE (ItemResourceId = '
.
$resource_id
.
')'
;
if
(!
$with_primary
)
{
$sql
.=
' AND (PrimaryCat = 0)'
;
}
return
$this
->
Conn
->
GetCol
(
$sql
);
}
/**
* Adds new and removes old additional categories from category item
*
* @param kCatDBItem $object
*/
function
processAdditionalCategories
(&
$object
,
$mode
)
{
if
(!
array_key_exists
(
'MoreCategories'
,
$object
->
VirtualFields
))
{
// given category item doesn't require such type of processing
return
;
}
$process_categories
=
$object
->
GetDBField
(
'MoreCategories'
);
if
(
$process_categories
===
''
)
{
// field was not in submit & have default value (when no categories submitted, then value is null)
return
;
}
if
(
$mode
==
'create'
)
{
// prevents first additional category to become primary
$object
->
assignPrimaryCategory
();
}
$process_categories
=
$process_categories
?
explode
(
'|'
,
substr
(
$process_categories
,
1
,
-
1
))
:
Array
();
$existing_categories
=
$this
->
getItemCategories
(
$object
->
GetDBField
(
'ResourceId'
));
$add_categories
=
array_diff
(
$process_categories
,
$existing_categories
);
foreach
(
$add_categories
as
$category_id
)
{
$object
->
assignToCategory
(
$category_id
);
}
$remove_categories
=
array_diff
(
$existing_categories
,
$process_categories
);
foreach
(
$remove_categories
as
$category_id
)
{
$object
->
removeFromCategory
(
$category_id
);
}
}
/**
* Creates category item & redirects to confirmation template (front-end only)
*
* @param kEvent $event
*/
function
OnUpdate
(&
$event
)
{
$use_pending
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'UsePendingEditing'
);
if
(
$this
->
Application
->
isAdminUser
||
!
$use_pending
)
{
parent
::
OnUpdate
(
$event
);
$this
->
SetFrontRedirectTemplate
(
$event
,
'modify'
);
return
;
}
$object
=&
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
));
/* @var $object kCatDBItem */
$items_info
=
$this
->
Application
->
GetVar
(
$event
->
getPrefixSpecial
(
true
));
if
(
$items_info
)
{
$perm_helper
=&
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
/* @var $perm_helper kPermissionsHelper */
$temp_handler
=&
$this
->
Application
->
recallObject
(
$event
->
getPrefixSpecial
().
'_TempHandler'
,
'kTempTablesHandler'
);
/* @var $temp_handler kTempTablesHandler */
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
$file_helper
=&
$this
->
Application
->
recallObject
(
'FileHelper'
);
/* @var $file_helper FileHelper */
foreach
(
$items_info
as
$id
=>
$field_values
)
{
$object
->
Load
(
$id
);
$edit_perm
=
$perm_helper
->
ModifyCheckPermission
(
$object
->
GetDBField
(
$owner_field
),
$object
->
GetDBField
(
'CategoryId'
),
$event
->
Prefix
);
if
(
$use_pending
&&
!
$object
->
GetDBField
(
'OrgId'
)
&&
(
$edit_perm
==
STATUS_PENDING
))
{
// pending editing enabled + not pending copy -> get/create pending copy & save changes to it
$original_id
=
$object
->
GetID
();
$original_resource_id
=
$object
->
GetDBField
(
'ResourceId'
);
$file_helper
->
PreserveItemFiles
(
$field_values
);
$object
->
Load
(
$original_id
,
'OrgId'
);
if
(!
$object
->
isLoaded
())
{
// 1. user has no pending copy of live item -> clone live item
$cloned_ids
=
$temp_handler
->
CloneItems
(
$event
->
Prefix
,
$event
->
Special
,
Array
(
$original_id
),
null
,
null
,
null
,
true
);
$object
->
Load
(
$cloned_ids
[
0
]);
$object
->
SetFieldsFromHash
(
$field_values
);
// 1a. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
$ci_table
=
$this
->
Application
->
getUnitOption
(
'ci'
,
'TableName'
);
$sql
=
'DELETE FROM '
.
$ci_table
.
'
WHERE ItemResourceId = '
.
$object
->
GetDBField
(
'ResourceId'
).
' AND PrimaryCat = 1'
;
$this
->
Conn
->
Query
(
$sql
);
// 1b. copy main item categoryitems to cloned item
$sql
=
'INSERT INTO '
.
$ci_table
.
' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
SELECT CategoryId, '
.
$object
->
GetDBField
(
'ResourceId'
).
' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
FROM '
.
$ci_table
.
'
WHERE ItemResourceId = '
.
$original_resource_id
;
$this
->
Conn
->
Query
(
$sql
);
// 1c. put cloned id to OrgId field of item being cloned
$object
->
SetDBField
(
'Status'
,
STATUS_PENDING_EDITING
);
$object
->
SetDBField
(
'OrgId'
,
$original_id
);
}
else
{
// 2. user has pending copy of live item -> just update field values
$object
->
SetFieldsFromHash
(
$field_values
);
}
// update id in request (used for redirect in mod-rewrite mode)
$this
->
Application
->
SetVar
(
$event
->
getPrefixSpecial
().
'_id'
,
$object
->
GetID
());
}
else
{
// 3. already editing pending copy -> just update field values
$object
->
SetFieldsFromHash
(
$field_values
);
}
if
(
$object
->
Update
())
{
$event
->
status
=
erSUCCESS
;
}
else
{
$event
->
status
=
erFAIL
;
$event
->
redirect
=
false
;
break
;
}
}
}
$this
->
SetFrontRedirectTemplate
(
$event
,
'modify'
);
}
/**
* Sets next template to one required for front-end after adding/modifying item
*
* @param kEvent $event
* @param string $template_key - {suggest,modify}
*/
function
SetFrontRedirectTemplate
(&
$event
,
$template_key
)
{
if
(
$this
->
Application
->
isAdminUser
||
$event
->
status
!=
erSUCCESS
)
{
return
;
}
// prepare redirect template
$object
=&
$event
->
getObject
();
$is_active
=
(
$object
->
GetDBField
(
'Status'
)
==
STATUS_ACTIVE
);
$next_template
=
$is_active
?
'confirm_template'
:
'pending_confirm_template'
;
$event
->
redirect
=
$this
->
Application
->
GetVar
(
$template_key
.
'_'
.
$next_template
);
$event
->
SetRedirectParam
(
'opener'
,
's'
);
// send email events
$perm_prefix
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'PermItemPrefix'
);
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
$owner_id
=
$object
->
GetDBField
(
$owner_field
);
switch
(
$event
->
Name
)
{
case
'OnCreate'
:
$event_suffix
=
$is_active
?
'ADD'
:
'ADD.PENDING'
;
$this
->
Application
->
EmailEventAdmin
(
$perm_prefix
.
'.'
.
$event_suffix
);
// there are no ADD.PENDING event for admin :(
$this
->
Application
->
EmailEventUser
(
$perm_prefix
.
'.'
.
$event_suffix
,
$owner_id
);
break
;
case
'OnUpdate'
:
$event_suffix
=
$is_active
?
'MODIFY'
:
'MODIFY.PENDING'
;
$user_id
=
is_numeric
(
$object
->
GetDBField
(
'ModifiedById'
)
)
?
$object
->
GetDBField
(
'ModifiedById'
)
:
$owner_id
;
$this
->
Application
->
EmailEventAdmin
(
$perm_prefix
.
'.'
.
$event_suffix
);
// there are no ADD.PENDING event for admin :(
$this
->
Application
->
EmailEventUser
(
$perm_prefix
.
'.'
.
$event_suffix
,
$user_id
);
break
;
}
}
/**
* Apply same processing to each item beeing selected in grid
*
* @param kEvent $event
* @access private
*/
function
iterateItems
(&
$event
)
{
if
(
$event
->
Name
!=
'OnMassApprove'
&&
$event
->
Name
!=
'OnMassDecline'
)
{
return
parent
::
iterateItems
(
$event
);
}
if
(
$this
->
Application
->
CheckPermission
(
'SYSTEM_ACCESS.READONLY'
,
1
))
{
$event
->
status
=
erFAIL
;
return
;
}
$object
=&
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
)
);
/* @var $object kCatDBItem */
$ids
=
$this
->
StoreSelectedIDs
(
$event
);
if
(
$ids
)
{
foreach
(
$ids
as
$id
)
{
$object
->
Load
(
$id
);
switch
(
$event
->
Name
)
{
case
'OnMassApprove'
:
$ret
=
$object
->
ApproveChanges
();
break
;
case
'OnMassDecline'
:
$ret
=
$object
->
DeclineChanges
();
break
;
}
if
(!
$ret
)
{
$event
->
status
=
erFAIL
;
$event
->
redirect
=
false
;
break
;
}
}
}
$this
->
clearSelectedIDs
(
$event
);
}
/**
* Deletes items & preserves clean env
*
* @param kEvent $event
*/
function
OnDelete
(&
$event
)
{
parent
::
OnDelete
(
$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)
*
* @param kEvent $event
* @return bool
*/
function
checkItemStatus
(&
$event
)
{
$object
=&
$event
->
getObject
();
if
(!
$object
->
isLoaded
())
{
$this
->
_errorNotFound
(
$event
);
return
true
;
}
$status
=
$object
->
GetDBField
(
'Status'
);
$user_id
=
$this
->
Application
->
RecallVar
(
'user_id'
);
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
if
((
$status
==
STATUS_PENDING_EDITING
||
$status
==
STATUS_PENDING
)
&&
(
$object
->
GetDBField
(
$owner_field
)
==
$user_id
))
{
return
true
;
}
return
$status
==
STATUS_ACTIVE
;
}
/**
* Set's correct sorting for list
* based on data provided with event
*
* @param kEvent $event
* @access private
* @see OnListBuild
*/
function
SetSorting
(&
$event
)
{
if
(!
$this
->
Application
->
isAdmin
)
{
$event
->
setEventParam
(
'same_special'
,
true
);
}
parent
::
SetSorting
(
$event
);
}
/**
* Returns current per-page setting for list
*
* @param kEvent $event
* @return int
*/
function
getPerPage
(&
$event
)
{
if
(!
$this
->
Application
->
isAdmin
)
{
$event
->
setEventParam
(
'same_special'
,
true
);
}
return
parent
::
getPerPage
(
$event
);
}
function
getOwnerField
(
$prefix
)
{
$owner_field
=
$this
->
Application
->
getUnitOption
(
$prefix
,
'OwnerField'
);
if
(!
$owner_field
)
{
$owner_field
=
'CreatedById'
;
}
return
$owner_field
;
}
/**
* Creates virtual image fields for item
*
* @param kEvent $event
*/
function
OnAfterConfigRead
(&
$event
)
{
parent
::
OnAfterConfigRead
(
$event
);
if
(
defined
(
'IS_INSTALL'
)
&&
IS_INSTALL
)
{
return
;
}
if
(
!
$this
->
Application
->
isAdmin
)
{
$file_helper
=&
$this
->
Application
->
recallObject
(
'FileHelper'
);
/* @var $file_helper FileHelper */
$file_helper
->
createItemFiles
(
$event
->
Prefix
,
true
);
// create image fields
$file_helper
->
createItemFiles
(
$event
->
Prefix
,
false
);
// create file fields
}
$this
->
changeSortings
(
$event
);
// add grids for advanced view (with primary category column)
$grids
=
$this
->
Application
->
getUnitOption
(
$this
->
Prefix
,
'Grids'
);
$process_grids
=
Array
(
'Default'
,
'Radio'
);
foreach
(
$process_grids
as
$process_grid
)
{
$grid_data
=
$grids
[
$process_grid
];
$grid_data
[
'Fields'
][
'CachedNavbar'
]
=
Array
(
'title'
=>
'la_col_Path'
,
'data_block'
=>
'grid_primary_category_td'
,
'filter_block'
=>
'grid_like_filter'
);
$grids
[
$process_grid
.
'ShowAll'
]
=
$grid_data
;
}
$this
->
Application
->
setUnitOption
(
$this
->
Prefix
,
'Grids'
,
$grids
);
// add options for CategoryId field (quick way to select item's primary category)
$category_helper
=&
$this
->
Application
->
recallObject
(
'CategoryHelper'
);
/* @var $category_helper CategoryHelper */
$virtual_fields
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'VirtualFields'
);
$virtual_fields
[
'CategoryId'
][
'default'
]
=
(
int
)
$this
->
Application
->
GetVar
(
'm_cat_id'
);
$virtual_fields
[
'CategoryId'
][
'options'
]
=
$category_helper
->
getStructureTreeAsOptions
();
$this
->
Application
->
setUnitOption
(
$event
->
Prefix
,
'VirtualFields'
,
$virtual_fields
);
}
function
changeSortings
(&
$event
)
{
$remove_sortings
=
Array
();
if
(!
$this
->
Application
->
isAdmin
)
{
// remove Pick sorting on Front-end, when not required
$config_mapping
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ConfigMapping'
);
if
(!
isset
(
$config_mapping
[
'ForceEditorPick'
])
||
!
$this
->
Application
->
ConfigValue
(
$config_mapping
[
'ForceEditorPick'
]))
{
$remove_sortings
[]
=
'EditorsPick'
;
}
}
else
{
// remove all forced sortings in Admin Console
$remove_sortings
=
array_merge
(
$remove_sortings
,
Array
(
'Priority'
,
'EditorsPick'
));
}
if
(!
$remove_sortings
)
{
return
;
}
$list_sortings
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ListSortings'
,
Array
());
foreach
(
$list_sortings
as
$special
=>
$sorting_fields
)
{
foreach
(
$remove_sortings
as
$sorting_field
)
{
unset
(
$list_sortings
[
$special
][
'ForcedSorting'
][
$sorting_field
]);
}
}
$this
->
Application
->
setUnitOption
(
$event
->
Prefix
,
'ListSortings'
,
$list_sortings
);
}
/**
* Returns file contents associated with item
*
* @param kEvent $event
*/
function
OnDownloadFile
(&
$event
)
{
$object
=&
$event
->
getObject
();
/* @var $object kDBItem */
$event
->
status
=
erSTOP
;
$field
=
$this
->
Application
->
GetVar
(
'field'
);
if
(!
preg_match
(
'/^File([
\d
]+)/'
,
$field
))
{
return
;
}
$file_helper
=&
$this
->
Application
->
recallObject
(
'FileHelper'
);
/* @var $file_helper FileHelper */
$filename
=
$object
->
GetField
(
$field
,
'full_path'
);
$file_helper
->
DownloadFile
(
$filename
);
}
/**
* Saves user's vote
*
* @param kEvent $event
*/
function
OnMakeVote
(&
$event
)
{
$event
->
status
=
erSTOP
;
if
(
$this
->
Application
->
GetVar
(
'ajax'
)
!=
'yes'
)
{
// this is supposed to call from AJAX only
return
;
}
$rating_helper
=&
$this
->
Application
->
recallObject
(
'RatingHelper'
);
/* @var $rating_helper RatingHelper */
$object
=&
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
)
);
/* @var $object kDBItem */
$object
->
Load
(
$this
->
Application
->
GetVar
(
'id'
)
);
echo
$rating_helper
->
makeVote
(
$object
);
}
/**
* [HOOK] Allows to add cloned subitem to given prefix
*
* @param kEvent $event
*/
function
OnCloneSubItem
(&
$event
)
{
parent
::
OnCloneSubItem
(
$event
);
if
(
$event
->
MasterEvent
->
Prefix
==
'fav'
)
{
$clones
=
$this
->
Application
->
getUnitOption
(
$event
->
MasterEvent
->
Prefix
,
'Clones'
);
$subitem_prefix
=
$event
->
Prefix
.
'-'
.
$event
->
MasterEvent
->
Prefix
;
$clones
[
$subitem_prefix
][
'ParentTableKey'
]
=
'ResourceId'
;
$clones
[
$subitem_prefix
][
'ForeignKey'
]
=
'ResourceId'
;
$this
->
Application
->
setUnitOption
(
$event
->
MasterEvent
->
Prefix
,
'Clones'
,
$clones
);
}
}
}
Event Timeline
Log In to Comment