Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1101051
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
Fri, Aug 15, 6:12 PM
Size
95 KB
Mime Type
text/x-php
Expires
Sun, Aug 17, 6:12 PM (5 h, 59 m)
Engine
blob
Format
Raw Data
Handle
713096
Attached To
rINP In-Portal
cat_event_handler.php
View Options
<?php
/**
* @version $Id: cat_event_handler.php 16621 2018-04-06 14:17:13Z 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 standard permission mapping
*
* @return void
* @access protected
* @see kEventHandler::$permMapping
*/
protected
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'
),
'OnAfterDeleteOriginal'
=>
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
),
'OnReviewHelpful'
=>
Array
(
'self'
=>
true
),
);
$this
->
permMapping
=
array_merge
(
$this
->
permMapping
,
$permissions
);
}
/**
* Load item if id is available
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
LoadItem
(
kEvent
$event
)
{
/** @var kDBItem $object */
$object
=
$event
->
getObject
();
$id
=
$this
->
getPassedID
(
$event
);
if
(
$object
->
Load
(
$id
)
)
{
/** @var Params $actions */
$actions
=
$this
->
Application
->
recallObject
(
'kActions'
);
$actions
->
Set
(
$event
->
getPrefixSpecial
()
.
'_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 user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public
function
CheckPermission
(
kEvent
$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
);
/** @var kPermissionsHelper $perm_helper */
$perm_helper
=
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
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
)
||
(
$event
->
Special
==
'export'
&&
$event
->
Name
==
'OnNew'
)
)
{
/** @var kPermissionsHelper $perm_helper */
$perm_helper
=
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
$perm_value
=
$this
->
Application
->
CheckPermission
(
'in-portal:main_import.view'
);
return
$perm_helper
->
finalizePermissionCheck
(
$event
,
$perm_value
);
}
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
(
'OnStoreSelected'
,
'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
)
{
/** @var kPermissionsHelper $perm_helper */
$perm_helper
=
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
// 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
* @return void
* @access protected
*/
protected
function
OnCopy
(
$event
)
{
$this
->
Application
->
RemoveVar
(
'clipboard'
);
/** @var kClipboardHelper $clipboard_helper */
$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
* @return void
* @access protected
*/
protected
function
OnCut
(
$event
)
{
$this
->
Application
->
RemoveVar
(
'clipboard'
);
/** @var kClipboardHelper $clipboard_helper */
$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
)
{
/** @var kPermissionsHelper $perm_helper */
$perm_helper
=
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
$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
* @return void
* @access protected
*/
protected
function
OnPaste
(
$event
)
{
if
(
$this
->
Application
->
CheckPermission
(
'SYSTEM_ACCESS.READONLY'
,
1
)
||
!
$this
->
_checkPastePermission
(
$event
)
)
{
$event
->
status
=
kEvent
::
erFAIL
;
return
;
}
$clipboard_data
=
$event
->
getEventParam
(
'clipboard_data'
);
if
(
!
$clipboard_data
[
'cut'
]
&&
!
$clipboard_data
[
'copy'
]
)
{
return
;
}
if
(
$clipboard_data
[
'copy'
]
)
{
/** @var kTempTablesHandler $temp */
$temp
=
$this
->
Application
->
recallObject
(
$event
->
getPrefixSpecial
()
.
'_TempHandler'
,
'kTempTablesHandler'
);
$this
->
Application
->
SetVar
(
'ResetCatBeforeClone'
,
1
);
// used in "kCatDBEventHandler::OnBeforeClone"
$temp
->
CloneItems
(
$event
->
Prefix
,
$event
->
Special
,
$clipboard_data
[
'copy'
]);
}
if
(
$clipboard_data
[
'cut'
]
)
{
/** @var kCatDBItem $object */
$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
* @return void
* @access protected
*/
protected
function
OnMassDelete
(
kEvent
$event
)
{
if
(
$this
->
Application
->
CheckPermission
(
'SYSTEM_ACCESS.READONLY'
,
1
)
)
{
$event
->
status
=
kEvent
::
erFAIL
;
return
;
}
$ids
=
$this
->
StoreSelectedIDs
(
$event
);
$to_delete
=
Array
();
$recycle_bin
=
$this
->
Application
->
ConfigValue
(
'RecycleBinFolder'
);
if
(
$recycle_bin
)
{
/** @var CategoriesItem $rb */
$rb
=
$this
->
Application
->
recallObject
(
'c.recycle'
,
NULL
,
array
(
'skip_autoload'
=>
true
));
$rb
->
Load
(
$recycle_bin
);
/** @var kCatDBItem $object */
$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
;
}
/** @var kTempTablesHandler $temp_handler */
$temp_handler
=
$this
->
Application
->
recallObject
(
$event
->
getPrefixSpecial
()
.
'_TempHandler'
,
'kTempTablesHandler'
);
$event
->
setEventParam
(
'ids'
,
$ids
);
$this
->
customProcessing
(
$event
,
'before'
);
$ids
=
$event
->
getEventParam
(
'ids'
);
if
(
$ids
)
{
$temp_handler
->
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'
);
$keywords
=
$event
->
getEventParam
(
'keyword_string'
);
$type
=
$this
->
Application
->
GetVar
(
'search_type'
,
'simple'
);
if
(
$keywords
)
{
// processing keyword_string param of ListProducts tag
$this
->
Application
->
SetVar
(
'keywords'
,
$keywords
);
$type
=
'simple'
;
}
$search_event
=
$event_mapping
[
$type
];
$this
->
$search_event
(
$event
);
/** @var kDBList $object */
$object
=
$event
->
getObject
();
/** @var kSearchHelper $search_helper */
$search_helper
=
$this
->
Application
->
recallObject
(
'SearchHelper'
);
$search_sql
=
' FROM '
.
$search_helper
->
getSearchTable
()
.
' search_result
JOIN %1$s ON %1$s.ResourceId = search_result.ResourceId'
;
$sql
=
str_replace
(
'FROM %1$s'
,
$search_sql
,
$object
->
GetPlainSelectSQL
());
$object
->
SetSelectSQL
(
$sql
);
$object
->
addCalculatedField
(
'Relevance'
,
'search_result.Relevance'
);
$type_clauses
[
'search'
][
'include'
]
=
'PrimaryCat = 1 AND ('
.
TABLE_PREFIX
.
'Categories.Status = '
.
STATUS_ACTIVE
.
')'
;
$type_clauses
[
'search'
][
'except'
]
=
'PrimaryCat = 1 AND ('
.
TABLE_PREFIX
.
'Categories.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)
/** @var kDBList $list */
$list
=
$this
->
Application
->
recallObject
(
$prefix_special
);
$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'
);
}
}
/** @var kCatDBItem $p_item */
$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
$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
.
'Categories.TreeLeft BETWEEN '
.
$tree_indexes
[
'TreeLeft'
].
' AND '
.
$tree_indexes
[
'TreeRight'
];
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected
function
SetCustomQuery
(
kEvent
$event
)
{
parent
::
SetCustomQuery
(
$event
);
/** @var kCatDBList $object */
$object
=
$event
->
getObject
();
// add category filter if needed
if
(
$event
->
Special
!=
'showall'
&&
$event
->
Special
!=
'user'
)
{
if
(
(
string
)
$event
->
getEventParam
(
'parent_cat_id'
)
!==
''
)
{
$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
);
}
$this
->
applyViewPermissionFilter
(
$object
);
$types
=
$event
->
getEventParam
(
'types'
);
$this
->
applyItemStatusFilter
(
$object
,
$types
);
$except_types
=
$event
->
getEventParam
(
'except'
);
$type_clauses
=
$this
->
getTypeClauses
(
$event
);
/** @var kSearchHelper $search_helper */
$search_helper
=
$this
->
Application
->
recallObject
(
'SearchHelper'
);
$search_helper
->
SetComplexFilter
(
$event
,
$type_clauses
,
$types
,
$except_types
);
}
/**
* Adds filter, that uses *.VIEW permissions to determine if an item should be shown to a user.
*
* @param kCatDBList $object Object.
*
* @return void
* @access protected
*/
protected
function
applyViewPermissionFilter
(
kCatDBList
$object
)
{
if
(
!
$this
->
Application
->
ConfigValue
(
'CheckViewPermissionsInCatalog'
)
)
{
return
;
}
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 item list view permission is checked instead of CATEGORY.VIEW
/** @var kCountHelper $count_helper */
$count_helper
=
$this
->
Application
->
recallObject
(
'CountHelper'
);
list
(
$view_perm
,
$view_filter
)
=
$count_helper
->
GetPermissionClause
(
$object
->
Prefix
,
'perm'
);
$object
->
addFilter
(
'perm_filter2'
,
$view_filter
);
}
$object
->
addFilter
(
'perm_filter'
,
'perm.PermId = '
.
$view_perm
);
}
/**
* 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
.
'Categories.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 kDBItem|kDBList $object
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
prepareObject
(&
$object
,
kEvent
$event
)
{
$this
->
prepareItemStatuses
(
$event
);
$object
->
addCalculatedField
(
'CachedNavbar'
,
'l'
.
$this
->
Application
->
GetVar
(
'm_lang'
)
.
'_CachedNavbar'
);
if
(
$event
->
Special
==
'export'
||
$event
->
Special
==
'import'
)
{
/** @var kCatDBItemExportHelper $export_helper */
$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)'
);
}
/**
* Calculates hot limit for current item's table
*
* @param kEvent $event
* @return float
* @access protected
*/
protected
function
CalculateHotLimit
(
$event
)
{
$property_map
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ItemPropertyMappings'
);
if
(
!
$property_map
)
{
return
0.00
;
}
$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
* @return void
* @access protected
*/
protected
function
OnBeforeItemUpdate
(
kEvent
$event
)
{
parent
::
OnBeforeItemUpdate
(
$event
);
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
// 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
);
}
}
/**
* Occurs after loading item, 'id' parameter
* allows to get id of item that was loaded
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnAfterItemLoad
(
kEvent
$event
)
{
parent
::
OnAfterItemLoad
(
$event
);
$special
=
substr
(
$event
->
Special
,
-
6
);
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
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'
]);
}
}
// substituting pending status value for pending editing
if
(
$object
->
HasField
(
'OrgId'
)
&&
$object
->
GetDBField
(
'OrgId'
)
>
0
&&
$object
->
GetDBField
(
'Status'
)
==
-
2
)
{
$new_options
=
Array
();
$options
=
$object
->
GetFieldOption
(
'Status'
,
'options'
,
false
,
Array
());
foreach
(
$options
as
$key
=>
$val
)
{
if
(
$key
==
2
)
{
$key
=
-
2
;
}
$new_options
[
$key
]
=
$val
;
}
$object
->
SetFieldOption
(
'Status'
,
'options'
,
$new_options
);
}
if
(
!
$this
->
Application
->
isAdmin
)
{
// linking existing images for item with virtual fields
/** @var ImageHelper $image_helper */
$image_helper
=
$this
->
Application
->
recallObject
(
'ImageHelper'
);
$image_helper
->
LoadItemImages
(
$object
);
// linking existing files for item with virtual fields
/** @var FileHelper $file_helper */
$file_helper
=
$this
->
Application
->
recallObject
(
'FileHelper'
);
$file_helper
->
LoadItemFiles
(
$object
);
}
if
(
$object
->
isVirtualField
(
'MoreCategories'
)
)
{
// 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
)
.
'|'
:
''
);
}
}
/**
* Occurs after updating item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnAfterItemUpdate
(
kEvent
$event
)
{
parent
::
OnAfterItemUpdate
(
$event
);
$this
->
CalculateHotLimit
(
$event
);
if
(
substr
(
$event
->
Special
,
-
6
)
==
'import'
)
{
$this
->
setCustomExportColumns
(
$event
);
}
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
if
(
!
$this
->
Application
->
isAdmin
)
{
/** @var ImageHelper $image_helper */
$image_helper
=
$this
->
Application
->
recallObject
(
'ImageHelper'
);
// process image upload in virtual fields
$image_helper
->
SaveItemImages
(
$object
);
/** @var FileHelper $file_helper */
$file_helper
=
$this
->
Application
->
recallObject
(
'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'
);
}
}
if
(
$object
->
GetChangedFields
()
)
{
$now
=
adodb_mktime
();
$object
->
SetDBField
(
'Modified_date'
,
$now
);
$object
->
SetDBField
(
'Modified_time'
,
$now
);
$object
->
SetDBField
(
'ModifiedById'
,
$this
->
Application
->
RecallVar
(
'user_id'
));
}
}
/**
* Sets values for import process
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnAfterItemCreate
(
kEvent
$event
)
{
parent
::
OnAfterItemCreate
(
$event
);
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
if
(
substr
(
$event
->
Special
,
-
6
)
==
'import'
)
{
$this
->
setCustomExportColumns
(
$event
);
}
$object
->
assignPrimaryCategory
();
if
(
!
$this
->
Application
->
isAdmin
)
{
/** @var ImageHelper $image_helper */
$image_helper
=
$this
->
Application
->
recallObject
(
'ImageHelper'
);
// process image upload in virtual fields
$image_helper
->
SaveItemImages
(
$object
);
/** @var FileHelper $file_helper */
$file_helper
=
$this
->
Application
->
recallObject
(
'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
.
'SearchLogs
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
.
'SearchLogs'
);
}
$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
;
$keywords
=
$this
->
Application
->
unescapeRequestVariable
(
trim
(
$this
->
Application
->
GetVar
(
'keywords'
)));
/** @var kHTTPQuery $query_object */
$query_object
=
$this
->
Application
->
recallObject
(
'HTTPQuery'
);
/** @var kSearchHelper $search_helper */
$search_helper
=
$this
->
Application
->
recallObject
(
'SearchHelper'
);
$search_table
=
$search_helper
->
getSearchTable
();
$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'
))
{
$search_helper
->
ensureEmptySearchTable
();
$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'
);
/** @var kDBList $object */
$object
=
$event
->
getObject
();
$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
)
{
$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
(
!
$search_config
[
$field
][
'CustomFieldId'
]
&&
$object
->
GetFieldOption
(
$field
,
'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
$foreign_field
=
$search_config
[
$field
][
'ForeignField'
];
if
(
$foreign_field
)
{
$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.
$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
.
'Categories ON '
.
TABLE_PREFIX
.
'Categories.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'
)
{
$sub_search_ids
=
$event
->
MasterEvent
->
getEventParam
(
'ResultIds'
);
if
(
$sub_search_ids
!==
false
)
{
if
(
$sub_search_ids
)
{
$where_clause
.=
'AND ('
.
$items_table
.
'.ResourceId IN ('
.
implode
(
','
,
$sub_search_ids
)
.
'))'
;
}
else
{
$where_clause
.=
'AND FALSE'
;
}
}
}
// 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)';
}*/
if
(
count
(
$positive_words
)
>
1
)
{
$condition
=
$field
.
' LIKE "%'
.
implode
(
' '
,
$positive_words
)
.
'%"'
;
$revelance_parts
[]
=
'IF('
.
$condition
.
', '
.
$weight_sum
.
', 0)'
;
}
// search by partial word matches too
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
&&
$object
->
isField
(
'Hits'
))
{
$relevance_clause
.=
' + (Hits + 1) / (MAX(Hits) + 1) * '
.
$rel_pop
;
}
if
(
$rel_rating
&&
$object
->
isField
(
'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'
;
$this
->
Conn
->
Query
(
$sql
);
if
(
!
$search_table_exists
)
{
$sql
=
'ALTER TABLE '
.
$search_table
.
'
ADD INDEX (ResourceId),
ADD INDEX (Relevance)'
;
$this
->
Conn
->
Query
(
$sql
);
$this
->
Application
->
StoreVar
(
'search_performed'
,
1
);
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function
OnSubSearch
(
$event
)
{
// keep search results from other items after doing a sub-search on current item type
$this
->
Application
->
SetVar
(
'do_not_drop_search_table'
,
true
);
/** @var kSearchHelper $search_helper */
$search_helper
=
$this
->
Application
->
recallObject
(
'SearchHelper'
);
$search_table
=
$search_helper
->
getSearchTable
();
$sql
=
'SHOW TABLES LIKE "'
.
$search_table
.
'"'
;
$ids
=
array
();
if
(
$this
->
Conn
->
Query
(
$sql
)
)
{
$item_type
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ItemType'
);
// 1. get ids to be used as search bounds
$sql
=
'SELECT DISTINCT ResourceId
FROM '
.
$search_table
.
'
WHERE ItemType = '
.
$item_type
;
$ids
=
$this
->
Conn
->
GetCol
(
$sql
);
// 2. delete previously found ids
$sql
=
'DELETE FROM '
.
$search_table
.
'
WHERE ItemType = '
.
$item_type
;
$this
->
Conn
->
Query
(
$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
)
{
/** @var kHTTPQuery $query_object */
$query_object
=
$this
->
Application
->
recallObject
(
'HTTPQuery'
);
if
(
!
isset
(
$query_object
->
Post
[
'andor'
])
)
{
// used when navigating by pages or changing sorting in search results
return
;
}
$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'
);
/** @var kDBList $object */
$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
$local_table
=
TABLE_PREFIX
.
$record
[
'TableName'
];
$weight_sum
+=
$record
[
'Priority'
];
// counting weight sum; used when making relevance clause
// processing multilingual fields
if
(
$object
->
GetFieldOption
(
$field
,
'formatter'
)
==
'kMultiLanguage'
)
{
$field_name
=
'l'
.
$lang
.
'_'
.
$field
;
}
else
{
$field_name
=
$field
;
}
// processing fields from other tables
$foreign_field
=
$record
[
'ForeignField'
];
if
(
$foreign_field
)
{
$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'
;
/** @var kSearchHelper $search_helper */
$search_helper
=
$this
->
Application
->
recallObject
(
'SearchHelper'
);
// Building final search query.
$search_table
=
$search_helper
->
getSearchTable
();
$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
;
$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
]
=
$this
->
Application
->
unescapeRequestVariable
(
$keywords
[
$field
]);
if
(
$keywords
[
$field
])
{
$condition
=
sprintf
(
$condition_patterns
[
'is'
],
$field_name
,
$this
->
Conn
->
qstr
(
$keywords
[
$field
]
));
}
break
;
case
'multiselect'
:
$keywords
[
$field
]
=
$this
->
Application
->
unescapeRequestVariable
(
$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
]
=
$this
->
Application
->
unescapeRequestVariable
(
$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
(
$this
->
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
;
}
/**
* Returns human readable representation of searched data to be placed in search log
* @param string $type
* @param Array $search_data
* @return string
* @access protected
*/
protected
function
getHuman
(
$type
,
$search_data
)
{
// all 3 variables are retrieved from $search_data array
/** @var Array $search_config */
/** @var string $verb */
/** @var string $value */
$type
=
ucfirst
(
strtolower
(
$type
));
extract
(
$search_data
,
EXTR_SKIP
);
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
;
}
return
''
;
}
/**
* Set's correct page for list based on data provided with event
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected
function
SetPagination
(
kEvent
$event
)
{
/** @var kDBList $object */
$object
=
$event
->
getObject
();
// get PerPage (forced -> session -> config -> 10)
$object
->
SetPerPage
(
$this
->
getPerPage
(
$event
));
// main lists on Front-End have special get parameter for page
$page
=
$object
->
isMainList
()
?
$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
->
isMainList
()
)
{
// 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
* @return void
* @access protected
*/
protected
function
OnExport
(
kEvent
$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
);
/** @var kCatDBItemExportHelper $export_helper */
$export_helper
=
$this
->
Application
->
recallObject
(
'CatItemExportHelper'
);
$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
)
{
/** @var kCatDBItemExportHelper $export_object */
$export_object
=
$this
->
Application
->
recallObject
(
'CatItemExportHelper'
);
$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
);
$event
->
SetRedirectParam
(
'm_cat_id'
,
$this
->
Application
->
RecallVar
(
'ImportCategory'
));
$event
->
SetRedirectParam
(
'anchor'
,
'tab-'
.
$event
->
Prefix
);
$event
->
redirect
=
'catalog/catalog'
;
}
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
=
kEvent
::
erSTOP
;
}
/**
* Returns specific to each item type columns only
*
* @param kEvent $event
* @return Array
* @access protected
*/
public
function
getCustomExportColumns
(
kEvent
$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
* @return void
* @access protected
*/
protected
function
restorePrimaryImage
(
$event
)
{
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
if
(
!
$object
->
GetDBField
(
'ThumbnailImage'
)
&&
!
$object
->
GetDBField
(
'FullImage'
)
)
{
return
;
}
$image_data
=
$object
->
getPrimaryImageData
();
/** @var kDBItem $image */
$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'
));
}
if
(
$object
->
GetDBField
(
'ImageAlt'
)
)
{
$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
();
}
}
/**
* Detects if image url is specified in a given path (instead of path on disk)
*
* @param string $path
* @return bool
* @access protected
*/
protected
function
isURL
(
$path
)
{
return
preg_match
(
'#(http|https)://(.*)#'
,
$path
);
}
/**
* Prepares item for import/export operations
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnNew
(
kEvent
$event
)
{
parent
::
OnNew
(
$event
);
if
(
$event
->
Special
==
'import'
||
$event
->
Special
==
'export'
)
{
/** @var kCatDBItemExportHelper $export_helper */
$export_helper
=
$this
->
Application
->
recallObject
(
'CatItemExportHelper'
);
$export_helper
->
setRequiredFields
(
$event
);
}
}
/**
* Process items selected in item_selector
*
* @param kEvent $event
*/
function
OnProcessSelected
(
$event
)
{
$dst_field
=
$this
->
Application
->
RecallVar
(
'dst_field'
);
$selected_ids
=
$this
->
Application
->
GetVar
(
'selected_ids'
);
if
(
$dst_field
==
'ItemCategory'
)
{
// Item Edit -> Categories Tab -> New Categories
/** @var kCatDBItem $object */
$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'
]);
$event
->
SetRedirectParam
(
$event
->
getPrefixSpecial
()
.
'_id'
,
0
);
$event
->
SetRedirectParam
(
$event
->
getPrefixSpecial
()
.
'_event'
,
'OnExportBegin'
);
}
$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
);
/** @var kDBItem $object */
$object
=
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
));
$object
->
setID
(
$id
);
$object
->
SetFieldsFromHash
(
$field_values
);
$event
->
setEventParam
(
'form_data'
,
$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
());
}
/**
* Cancels item editing
* @param kEvent $event
* @return void
* @todo Used?
*/
function
OnCancelAction
(
$event
)
{
$event
->
redirect
=
$this
->
Application
->
GetVar
(
'cancel_template'
);
$event
->
SetRedirectParam
(
'pass'
,
'all,'
.
$event
->
getPrefixSpecial
());
}
/* === 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
)
{
/** @var kDBItem $object */
$object
=
$event
->
getObject
();
$object
->
SetDBField
(
$cached_field
,
$object
->
GetField
(
$id_field
));
}
/**
* Saves edited item into temp table
* If there is no id, new item is created in temp table
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnPreSave
(
kEvent
$event
)
{
parent
::
OnPreSave
(
$event
);
$use_pending_editing
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'UsePendingEditing'
);
if
(
$event
->
status
==
kEvent
::
erSUCCESS
&&
$use_pending_editing
)
{
// decision: clone or not clone
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
if
(
$object
->
GetID
()
==
0
||
$object
->
GetDBField
(
'OrgId'
)
>
0
)
{
// new items or cloned items shouldn't be cloned again
return
;
}
/** @var kPermissionsHelper $perm_helper */
$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
/** @var kTempTablesHandler $temp_handler */
$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 item's owner field
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnPreCreate
(
kEvent
$event
)
{
parent
::
OnPreCreate
(
$event
);
if
(
$event
->
status
!=
kEvent
::
erSUCCESS
)
{
return
;
}
/** @var kDBItem $object */
$object
=
$event
->
getObject
();
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
$object
->
SetDBField
(
$owner_field
,
$this
->
Application
->
RecallVar
(
'user_id'
));
}
/**
* Occurs before original item of item in pending editing got deleted (for hooking only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnBeforeDeleteOriginal
(
kEvent
$event
)
{
}
/**
* Occurs after original item of item in pending editing got deleted (for hooking only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnAfterDeleteOriginal
(
kEvent
$event
)
{
}
/**
* Occurs before an item has been cloned
* Id of newly created item is passed as event' 'id' param
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnBeforeClone
(
kEvent
$event
)
{
parent
::
OnBeforeClone
(
$event
);
/** @var kDBItem $object */
$object
=
$event
->
getObject
();
$object
->
SetDBField
(
'ResourceId'
,
0
);
// this will reset it
if
(
$this
->
Application
->
GetVar
(
'ResetCatBeforeClone'
)
)
{
$object
->
SetDBField
(
'CategoryId'
,
NULL
);
}
}
/**
* Set status for new category item based on user permission in category
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnBeforeItemCreate
(
kEvent
$event
)
{
parent
::
OnBeforeItemCreate
(
$event
);
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
// Don't allow creating records on behalf of another user.
if
(
!
$this
->
Application
->
isAdminUser
&&
!
defined
(
'CRON'
)
)
{
$object
->
SetDBField
(
$owner_field
,
$object
->
GetOriginalField
(
$owner_field
));
}
// Auto-assign records to currently logged-in user.
if
(
!
$object
->
GetDBField
(
$owner_field
)
)
{
$object
->
SetDBField
(
$owner_field
,
$this
->
Application
->
RecallVar
(
'user_id'
));
}
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
;
}
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
/** @var kPermissionsHelper $perm_helper */
$perm_helper
=
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
$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
=
kEvent
::
erFAIL
;
}
else
{
$object
->
SetDBField
(
'Status'
,
$item_status
);
}
}
/**
* Creates category item & redirects to confirmation template (front-end only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnCreate
(
kEvent
$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
* @param int $mode
*/
function
processAdditionalCategories
(&
$object
,
$mode
)
{
if
(
!
$object
->
isVirtualField
(
'MoreCategories'
)
)
{
// 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
* @return void
* @access protected
*/
protected
function
OnUpdate
(
kEvent
$event
)
{
$use_pending
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'UsePendingEditing'
);
if
(
$this
->
Application
->
isAdminUser
||
!
$use_pending
)
{
parent
::
OnUpdate
(
$event
);
$this
->
SetFrontRedirectTemplate
(
$event
,
'modify'
);
return
;
}
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
));
$items_info
=
$this
->
Application
->
GetVar
(
$event
->
getPrefixSpecial
(
true
));
if
(
$items_info
)
{
/** @var kPermissionsHelper $perm_helper */
$perm_helper
=
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
/** @var kTempTablesHandler $temp_handler */
$temp_handler
=
$this
->
Application
->
recallObject
(
$event
->
getPrefixSpecial
().
'_TempHandler'
,
'kTempTablesHandler'
);
$owner_field
=
$this
->
getOwnerField
(
$event
->
Prefix
);
/** @var FileHelper $file_helper */
$file_helper
=
$this
->
Application
->
recallObject
(
'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
);
$event
->
setEventParam
(
'form_data'
,
$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
);
$event
->
setEventParam
(
'form_data'
,
$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
);
$event
->
setEventParam
(
'form_data'
,
$field_values
);
}
if
(
$object
->
Update
())
{
$event
->
status
=
kEvent
::
erSUCCESS
;
}
else
{
$event
->
status
=
kEvent
::
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
->
isAdmin
||
$event
->
status
!=
kEvent
::
erSUCCESS
)
{
return
;
}
// prepare redirect template
/** @var kDBItem $object */
$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
->
emailAdmin
(
$perm_prefix
.
'.'
.
$event_suffix
);
// there are no ADD.PENDING event for admin :(
$this
->
Application
->
emailUser
(
$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
->
emailAdmin
(
$perm_prefix
.
'.'
.
$event_suffix
);
// there are no ADD.PENDING event for admin :(
$this
->
Application
->
emailUser
(
$perm_prefix
.
'.'
.
$event_suffix
,
$user_id
);
break
;
}
}
/**
* Apply same processing to each item being selected in grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
iterateItems
(
kEvent
$event
)
{
if
(
$event
->
Name
!=
'OnMassApprove'
&&
$event
->
Name
!=
'OnMassDecline'
)
{
parent
::
iterateItems
(
$event
);
}
if
(
$this
->
Application
->
CheckPermission
(
'SYSTEM_ACCESS.READONLY'
,
1
)
)
{
$event
->
status
=
kEvent
::
erFAIL
;
return
;
}
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
));
$ids
=
$this
->
StoreSelectedIDs
(
$event
);
if
(
$ids
)
{
foreach
(
$ids
as
$id
)
{
$object
->
Load
(
$id
);
switch
(
$event
->
Name
)
{
case
'OnMassApprove'
:
$object
->
ApproveChanges
();
break
;
case
'OnMassDecline'
:
$object
->
DeclineChanges
();
break
;
}
}
}
$this
->
clearSelectedIDs
(
$event
);
}
/**
* Deletes items & preserves clean env
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnDelete
(
kEvent
$event
)
{
parent
::
OnDelete
(
$event
);
if
(
$event
->
status
==
kEvent
::
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
* @access protected
*/
protected
function
checkItemStatus
(
kEvent
$event
)
{
/** @var kDBItem $object */
$object
=
$event
->
getObject
();
if
(
!
$object
->
isLoaded
()
)
{
if
(
$event
->
Special
!=
'previous'
&&
$event
->
Special
!=
'next'
)
{
$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
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected
function
SetSorting
(
kEvent
$event
)
{
if
(
!
$this
->
Application
->
isAdmin
)
{
$event
->
setEventParam
(
'same_special'
,
true
);
}
$types
=
$event
->
getEventParam
(
'types'
);
$types
=
$types
?
explode
(
','
,
$types
)
:
Array
();
if
(
in_array
(
'search'
,
$types
)
)
{
$event
->
setPseudoClass
(
'_List'
);
/** @var kDBList $object */
$object
=
$event
->
getObject
();
// 1. no user sorting - sort by relevance
$default_sortings
=
parent
::
_getDefaultSorting
(
$event
);
$default_sorting
=
key
(
$default_sortings
[
'Sorting'
])
.
','
.
current
(
$default_sortings
[
'Sorting'
]);
if
(
$object
->
isMainList
()
)
{
$sort_by
=
$this
->
Application
->
GetVar
(
'sort_by'
,
''
);
if
(
!
$sort_by
)
{
$this
->
Application
->
SetVar
(
'sort_by'
,
'Relevance,desc|'
.
$default_sorting
);
}
}
else
{
$sorting_settings
=
$this
->
getListSetting
(
$event
,
'Sortings'
);
$sort_by
=
trim
(
getArrayValue
(
$sorting_settings
,
'Sort1'
)
.
','
.
getArrayValue
(
$sorting_settings
,
'Sort1_Dir'
),
','
);
if
(
!
$sort_by
)
{
$event
->
setEventParam
(
'sort_by'
,
'Relevance,desc|'
.
$default_sorting
);
}
}
$this
->
_removeForcedSortings
(
$event
);
}
parent
::
SetSorting
(
$event
);
}
/**
* Removes forced sortings
*
* @param kEvent $event
*/
protected
function
_removeForcedSortings
(
kEvent
$event
)
{
/** @var Array $list_sortings */
$list_sortings
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ListSortings'
,
Array
());
foreach
(
$list_sortings
as
$special
=>
$sortings
)
{
unset
(
$list_sortings
[
$special
][
'ForcedSorting'
]);
}
$this
->
Application
->
setUnitOption
(
$event
->
Prefix
,
'ListSortings'
,
$list_sortings
);
}
/**
* Default sorting in search results only comes from relevance field
*
* @param kEvent $event
* @return Array
* @access protected
*/
protected
function
_getDefaultSorting
(
kEvent
$event
)
{
$types
=
$event
->
getEventParam
(
'types'
);
$types
=
$types
?
explode
(
','
,
$types
)
:
Array
();
return
in_array
(
'search'
,
$types
)
?
Array
()
:
parent
::
_getDefaultSorting
(
$event
);
}
/**
* Returns current per-page setting for list
*
* @param kEvent $event
* @return int
* @access protected
*/
protected
function
getPerPage
(
kEvent
$event
)
{
if
(
!
$this
->
Application
->
isAdmin
)
{
$event
->
setEventParam
(
'same_special'
,
true
);
}
return
parent
::
getPerPage
(
$event
);
}
/**
* Returns owner field for given prefix
*
* @param $prefix
* @return string
* @access protected
*/
protected
function
getOwnerField
(
$prefix
)
{
return
$this
->
Application
->
getUnitOption
(
$prefix
,
'OwnerField'
,
'CreatedById'
);
}
/**
* Creates virtual image fields for item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnAfterConfigRead
(
kEvent
$event
)
{
parent
::
OnAfterConfigRead
(
$event
);
if
(
defined
(
'IS_INSTALL'
)
&&
IS_INSTALL
)
{
$this
->
addViewPermissionJoin
(
$event
);
return
;
}
if
(
!
$this
->
Application
->
isAdmin
)
{
/** @var FileHelper $file_helper */
$file_helper
=
$this
->
Application
->
recallObject
(
'FileHelper'
);
$file_helper
->
createItemFiles
(
$event
->
Prefix
,
true
);
// create image fields
$file_helper
->
createItemFiles
(
$event
->
Prefix
,
false
);
// create file fields
}
$this
->
changeSortings
(
$event
)->
addViewPermissionJoin
(
$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)
/** @var CategoryHelper $category_helper */
$category_helper
=
$this
->
Application
->
recallObject
(
'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
);
}
/**
* Changes default sorting according to system settings.
*
* @param kEvent $event Event.
*
* @return self
* @access protected
*/
protected
function
changeSortings
(
kEvent
$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'
,
Array
());
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
$this
;
}
/** @var Array $list_sortings */
$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
);
return
$this
;
}
/**
* Adds permission table table JOIN clause only, when advanced catalog view permissions enabled.
*
* @param kEvent $event Event.
*
* @return self
* @access protected
*/
protected
function
addViewPermissionJoin
(
kEvent
$event
)
{
if
(
$this
->
Application
->
ConfigValue
(
'CheckViewPermissionsInCatalog'
)
)
{
$join_clause
=
'LEFT JOIN '
.
TABLE_PREFIX
.
'CategoryPermissionsCache perm ON perm.CategoryId = '
.
TABLE_PREFIX
.
'%3$sCategoryItems.CategoryId'
;
}
else
{
$join_clause
=
''
;
}
/** @var array $list_sqls */
$list_sqls
=
$this
->
Application
->
getUnitOption
(
$event
->
Prefix
,
'ListSQLs'
);
foreach
(
$list_sqls
as
$special
=>
$list_sql
)
{
$list_sqls
[
$special
]
=
str_replace
(
'{PERM_JOIN}'
,
$join_clause
,
$list_sql
);
}
$this
->
Application
->
setUnitOption
(
$event
->
Prefix
,
'ListSQLs'
,
$list_sqls
);
return
$this
;
}
/**
* Returns file contents associated with item
*
* @param kEvent $event
*/
function
OnDownloadFile
(
$event
)
{
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
();
$event
->
status
=
kEvent
::
erSTOP
;
$field
=
$this
->
Application
->
GetVar
(
'field'
);
if
(!
preg_match
(
'/^File([
\d
]+)/'
,
$field
))
{
return
;
}
/** @var FileHelper $file_helper */
$file_helper
=
$this
->
Application
->
recallObject
(
'FileHelper'
);
$filename
=
$object
->
GetField
(
$field
,
'full_path'
);
$file_helper
->
DownloadFile
(
$filename
);
}
/**
* Saves user's vote
*
* @param kEvent $event
*/
function
OnMakeVote
(
$event
)
{
$event
->
status
=
kEvent
::
erSTOP
;
if
(
$this
->
Application
->
GetVar
(
'ajax'
)
!=
'yes'
)
{
// this is supposed to call from AJAX only
return
;
}
/** @var RatingHelper $rating_helper */
$rating_helper
=
$this
->
Application
->
recallObject
(
'RatingHelper'
);
/** @var kCatDBItem $object */
$object
=
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
)
);
$object
->
Load
(
$this
->
Application
->
GetVar
(
'id'
)
);
echo
$rating_helper
->
makeVote
(
$object
);
}
/**
* Marks review as useful
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnReviewHelpful
(
$event
)
{
if
(
$this
->
Application
->
GetVar
(
'ajax'
)
==
'yes'
)
{
$event
->
status
=
kEvent
::
erSTOP
;
}
$review_id
=
(
int
)
$this
->
Application
->
GetVar
(
'review_id'
);
if
(
!
$review_id
)
{
return
;
}
/** @var SpamHelper $spam_helper */
$spam_helper
=
$this
->
Application
->
recallObject
(
'SpamHelper'
);
$spam_helper
->
InitHelper
(
$review_id
,
'ReviewHelpful'
,
strtotime
(
'+1 month'
)
-
strtotime
(
'now'
));
$field
=
(
int
)
$this
->
Application
->
GetVar
(
'helpful'
)
?
'HelpfulCount'
:
'NotHelpfulCount'
;
$sql
=
'SELECT '
.
$field
.
'
FROM '
.
$this
->
Application
->
getUnitOption
(
'rev'
,
'TableName'
)
.
'
WHERE '
.
$this
->
Application
->
getUnitOption
(
'rev'
,
'IDField'
)
.
' = '
.
$review_id
;
$count
=
$this
->
Conn
->
GetOne
(
$sql
);
if
(
$spam_helper
->
InSpamControl
()
)
{
if
(
$this
->
Application
->
GetVar
(
'ajax'
)
==
'yes'
)
{
echo
$count
;
}
return
;
}
$sql
=
'UPDATE '
.
$this
->
Application
->
getUnitOption
(
'rev'
,
'TableName'
)
.
'
SET '
.
$field
.
' = '
.
$field
.
' + 1
WHERE '
.
$this
->
Application
->
getUnitOption
(
'rev'
,
'IDField'
)
.
' = '
.
$review_id
;
$this
->
Conn
->
Query
(
$sql
);
if
(
$this
->
Conn
->
getAffectedRows
()
)
{
// db was changed -> review with such ID exists
$spam_helper
->
AddToSpamControl
();
}
if
(
$this
->
Application
->
GetVar
(
'ajax'
)
==
'yes'
)
{
echo
$count
+
1
;
}
}
/**
* [HOOK] Allows to add cloned subitem to given prefix
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnCloneSubItem
(
kEvent
$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
);
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
* @return void
* @access protected
*/
protected
function
OnAfterItemValidate
(
kEvent
$event
)
{
/** @var kDBItem $object */
$object
=
$event
->
getObject
();
$resource_id
=
$object
->
GetDBField
(
'ResourceId'
);
if
(
!
$resource_id
)
{
$object
->
SetDBField
(
'ResourceId'
,
$this
->
Application
->
NextResourceId
());
}
}
}
Event Timeline
Log In to Comment