0% found this document useful (0 votes)
4 views18 pages

Pat 162007597

The document details the creation of patch PAT162007597 for Content Server version 16.2.0, addressing performance issues with the Name filter on SmartUI browse for large folders. It includes various functions aimed at optimizing SQL queries and improving performance based on container sizes and user permissions. Key functions include context string generation, SQL statement modifications, and pagination handling for efficient data retrieval.

Uploaded by

testcorreo03
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views18 pages

Pat 162007597

The document details the creation of patch PAT162007597 for Content Server version 16.2.0, addressing performance issues with the Name filter on SmartUI browse for large folders. It includes various functions aimed at optimizing SQL queries and improving performance based on container sizes and user permissions. Key functions include context string generation, SQL statement modifications, and pagination handling for efficient data retrieval.

Uploaded by

testcorreo03
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 18

# Patch PAT162007597 created at Mon Jul 22 08:02:35 EDT 2024

#
# Issue: LPAD-126663
# Module:
# Version: Content Server 16.2.0 64-bit for Windows
# Update: 24.2.0 (2024-03),24.1.0 (2023-12),23.4.0 (2023-09)
#
# Description:
# Poor performance of Name filter on SmartUI browse for large folders
#
m {'kernel','lliapi','webclassification'}
o {'pat162007597::LLNode',&&lliapi::LLNode}
N LLNode
f NodeContainerContextGet
s
/**
* Return a context string for this container object. This can be used in the
creation of SQL to provide
* context to the size of the container that allows the DB to generate optimal
explain plans for the
* differing sizes
*
* @param {Dynamic} node Either the DAPINODE or RecArray to the object
*
* @return {String} Either an empty string or the context based on the container
size ie "4=4"
*/
function String NodeContainerContextGet( Dynamic node )

Assoc checkVal
String anchorString

checkVal = .NodeChildCount( node )

if ( checkVal.ok )

//
// the optimizers in SQL server, Oracle and probably others are using
optimistic algorithms
// testing found that since the SQL for a container of 10 items is the
same as the SQL for a container
// 1m items, explain or execution plans will be cached according to the
first execution and the context.
// What this sql fragment does is provide the optimizer a different SQL
statement based on the size of the
// of the container. This allows the optimizer to potentially produce
different plans based on that context.
// The rule here is take the number of children defined by the
childcount and divide by 100K and put that in the SQL
// as an always true term. For example:
// 0-100k --- 1=1
// 100k-200k --- 2=2
// 200k-300k --- 3=3
// 300k-400k --- 4=4
// 400k-500k --- 5=5
//
anchorString = Str.Format( " %1=%1",
Math.Round( ( checkVal.childCount / 10000 ) ) + 1 )
end

//
// if the checkVal.ok ! true, then not much to be done here.
// If there is a DB error etc then other places will get access to that
// and provide better context.
//

return anchorString

end

sEND
f _BrowseTagsReplace
s
/**
* @private
*
* this function replaces various tags generated in the SQL statements
*
* @param {Object} prgCtx Program session object
* @param {String} stmt The SQL statement to be changed
*
* @return {String}
*/
function String _BrowseTagsReplace( Object prgCtx, String stmt )

String nameColumn =
$LLIAPI.LanguagePkg.GetSQLSortString( prgCtx, 'wnm.Name' )
String lowerNameColumn =
$LLIAPI.LanguagePkg.GetSQLLowerString( prgCtx, 'wnm.Name' )
Boolean isMultilingual
= ._GetSelectWithPaging_IsMultilingual( prgCtx.DSession() )

if ( Length( stmt ) > 0 )

stmt = Str.ReplaceAll( stmt, '[filterjoin]', " LEFT OUTER JOIN


WebNodesFilter wnf ON wnm.DataID = wnf.DataID " )
stmt = Str.ReplaceAll( stmt, '[dversjoin]', " LEFT OUTER JOIN DVersData
dvd ON wnm.DataID = dvd.DocID AND [roottableAlias].VersionNum = dvd.Version AND
dvd.VerType IS NULL " )
stmt = Str.ReplaceAll( stmt, '[orderRef]', " LEFT OUTER JOIN
DTreeSubTypeOrderRef dso ON dso.SubType = [roottableAlias].SubType " )

stmt = Str.ReplaceAll( stmt, '[filterclause]', 'wnf.' )


stmt = Str.ReplaceAll( stmt, '[nameclause]', nameColumn )
stmt = Str.ReplaceAll( stmt, '[lowernameclause]', lowerNameColumn )
stmt = Str.ReplaceAll( stmt, '[subtypeclause]', isMultilingual ?
'dt.SubType' :'wnm.SubType' )
stmt = Str.ReplaceAll( stmt, '[roottableAlias]', isMultilingual ?
'dt' :'wnm' )

end

return stmt

end
sEND
f _GetBrowseJoinCondition
s
/*
* This method provides the join condition for browse type queries. On MSSQL, the
LEFT JOIN
* performs better than the INNER JOIN whereas the other db's are good with INNER
*/
function String _GetBrowseJoinCondition( Object prgCtx )

String retString = "INNER JOIN"

return retString

end
sEND
f _GetNewGulpSize
s
/**
* @private
*
* Returns the ideal gulp size based on the last percentGood retrieved.
* This method will improve performance in the case the user has no permission to a
number of objects,
* allowing the application to retrieve an extra number of objects other than the
one defined in pagination.
*
* The maxBrowseGulpSize is set to 2500 unless ActiveView is being used, and we may
not allow the user to change this value,
* since setting higher numbers won't cause improvements in performance.
*
* @param {Integer} numberRequired Number of rows required
* @param {Real} percentGood Percentage good ( value between 0.0 and 1.0 )
* @param {Boolean} allResults If TRUE then ActiveView is being used, so
ignore MaxBrowseGulpSize and return all results
*
* @return {Integer} gulpSize New gulp size to use
*
*/
function Integer _GetNewGulpSize(
Integer numberRequired,
Real percentGood,
Boolean allResults )

Integer gulpSize
Integer paddingFactor

Integer maxBrowseGulpSize = ( allResults ) ?


numberRequired : .fMaxBrowseGulpSize

//
// Make sure the percent good never gets to zero.
//

percentGood = Math.Max( percentGood, 0.001 )


//
// We are going to apply a padding factor to the queries.
// This is based on the percentage good and in most case help that
// extra little bit to prevent another gulp. Especially when the
// the percentages are low.
//

if ( percentGood < 0.1 )

paddingFactor = maxBrowseGulpSize

elseif ( percentGood < 0.30 )

paddingFactor = 50

elseif ( percentGood < 0.50 )

paddingFactor = 30

elseif ( percentGood < 0.70 )

paddingFactor = 15

elseif ( percentGood < 1.0 )

paddingFactor = 5
end

gulpSize = Math.Max( Math.Min( paddingFactor + (numberRequired * (1.0 /


percentGood ) ), maxBrowseGulpSize ), .fMaxBrowseGulpSize )

return gulpSize
end

sEND
f _GetSelectWithPaging_GetAnchor
s
/**
* @private
*
* Returns a SQL statement to fetch all potential items (unpermissioned) in the
container.
*
* @param {Object} dapiCtx
* @param {DAPINODE} node
* @param {Assoc} options
*
* @return {Assoc}
* @returnFeature {Boolean} ok FALSE if an error occurred, TRUE otherwise
* @returnFeature {String} errMsg Error message, if an error occurred
* @returnFeature {Dynamic} apiError Application error, if applicable
* @returnFeature {String} anchor The string that contains the anchor to the
parent depending on the browsemode
* @returnFeature {List} params Bind variables used for this statement
* @returnFeature {String} tableJoin The SQL fragment used to join the browse
sql to other tables
*
*/
function Assoc _GetSelectWithPaging_GetAnchor( Object dapiCtx, DAPINODE node, Assoc
options )

Assoc rtnVal
Dynamic apiError
List params
String anchor
String errMsg
String tableJoin

Boolean ok = TRUE

// LPAD-127345

if ( IsDefined( node ) )

//
// In most cases the parent params are always the node.pID
// the root object and the volume are checked.
//
// the anchor is the one required element needed for a browse operation
// in the case of the regular container browse it is the parent ID
//

if ( IsDefined( options.browseMode ) && ( options.browseMode in


{ "editconfig", "targetBrowse" } ) )

params = { node.pID }
anchor = "ParentID=:A0"

// Example of volumed node browse adjustment for editconfig and


target browse
// params = { node.pID, -node.pID }
// anchor = "ParentID in ( :A0, :A0 )"

else

params = { node.pID, node.pVolumeID }


anchor = "ParentID=:A0 AND OwnerID=:A0"

end

end

rtnVal.ok = ok
rtnVal.errMsg = errMsg
rtnVal.apiError = apiError
rtnVal.anchor = anchor
rtnVal.params = params
rtnVal.tableJoin = tableJoin

return rtnVal

end
sEND
f _GetSelectWithPaging_IsMultilingual
s
/**
* @private
*
* Returns if the current system is a monolingual or multilingual to allow the
optimization
* of the the browse SQL
*
* @param {Object} dapiCtx
*
* @return {Boolean}
*/
function Boolean _GetSelectWithPaging_IsMultilingual( Object dapiCtx )

Assoc checkVal

Boolean isMultilingual = FALSE


Object prgCtx = dapiCtx.fPrgCtx

checkVal = $LLIAPI.LanguagePkg.IsMultilingual( prgCtx )

if ( checkVal.ok == TRUE )

isMultilingual = checkVal.isMultilingual

end

return isMultilingual

end
sEND
f _GetSelectWithPaging_Paging
s
/**
* @private
*
* Returns a SQL statement that modifies the incoming sql to get wrapped
* with paging SQL. If the options states sql paging is not to be used then
* no change is made to the stmt. Called from _GetSelectWithPaging
*
* @param {Object} prgCtx User session
* @param {String} stmt sql string to wrap with the paging sql
* @param {Assoc} options options assoc indicating if sql pagin
should be used
*
* @return {Assoc}
* @returnFeature {Boolean} ok
* @returnFeature {String} errMsg
* @returnFeature {Dynamic} apiError
* @returnFeature {Assoc} stmt SQL statement
*
* @private
*/
function Assoc _GetSelectWithPaging_Paging( Object prgCtx, String stmt, Assoc
options )

Assoc rtnVal
Dynamic apiError
String errMsg
String newStmt

Boolean ok = TRUE
Boolean isOracle = prgCtx.fDBConnect.IsOracle()
Boolean isOracle12c = prgCtx.fDBConnect.IsOracle12c()
Boolean isMSSQL = prgCtx.fDBConnect.IsMSSQL()
Boolean sqlPaginationEnabled = CAPI.IniGet(

prgCtx.fDBConnect.fLogin,
'SystemAdministration',
'OptimizedBrowsePaginati
onEnabled',
TRUE )
Integer maxChildSizeForNonPaging = 1000

// the kini value can override any settings. This is a safety switch
options.sqlPaging = sqlPaginationEnabled ? options.sqlPaging : FALSE

if ( !sqlPaginationEnabled )

echoDebug( " ---- SQL Pagination Disabled" )

end

if ( IsDefined( options.childCount ) && options.childCount <


maxChildSizeForNonPaging )

// LPAD-127345
echo( "_GetSelectWithPaging_Paging: turning off sql paginaiton" )

options.sqlPaging = FALSE

end

if ( options.sqlPaging )

.fIsPagingSQLPagination = TRUE

if ( isMSSQL || isOracle12c )

newStmt = stmt + " OFFSET :B1 ROWS FETCH NEXT :B2 ROWS ONLY "

elseif ( isOracle )

newStmt = Str.Format(
"SELECT /*+ BIND_AWARE NOPARALLEL */ OwnerID,
DataID, Catalog, GroupID, PermID FROM " +
"( SELECT a.*, rownum r__ FROM ( %1 ) a WHERE rownum <= :B2
) " +
"WHERE r__ >= :B1",
stmt )

else

newStmt = stmt + " LIMIT :B1 OFFSET :B2"

end

else

.fIsPagingSQLPagination = FALSE
newStmt = stmt

end

rtnVal.ok = ok
rtnVal.errMsg = errMsg
rtnVal.apiError = apiError
rtnVal.stmt = newStmt

return rtnVal

end
sEND
f _GetSelectWithPaging_clauseTypeFilter
s
/**
* @private
*
* Returns SQL fragment used to filter based on the name
*
* @param {Object} dapiCtx DAPI session object
* @param {DAPINODE} node The browse page node
* @param {String} viewName The database view name
* @param {String} userPrefLanguage The user prefered language
* @param {String} sortField The view column name to sort on
* @param {Assoc} options An assoc containing SQL options. See
{@link _ValidateOptions}
*
* @return {Assoc}
* @returnFeature {Boolean} ok FALSE if an error occurred, TRUE otherwise
* @returnFeature {String} errMsg Error message, if an error occurred
* @returnFeature {Dynamic} apiError Application error, if applicable
* @returnFeature {Boolean} hasFilter Boolean indicating if the query has any
additional filters.
* @returnFeature {Assoc} clause assoc with info about a fragment of a SQL
clause
* @returnFeature {String} sql SQL fragment
* @returnFeature {List} params The first element contains the parent ID,
the second (optional) parameter contains filtering data.
*/
function Assoc _GetSelectWithPaging_clauseTypeFilter(
Object dapiCtx,
DAPINODE node,
String viewName,
String userPrefLanguage,
String sortField,
Assoc options )

Assoc checkVal
Assoc clause
Assoc rtnVal
Dynamic apiError
List params
String errMsg
String typeFilterClause

Boolean ok = TRUE
Object dbConnect = dapiCtx.fDBConnect
Boolean hasFilter = FALSE
Boolean IsPostgreSQL = dapiCtx.fPrgCtx.fDBConnect.IsPostgreSQL()

if ( IsDefined( options.filterValue ) && Length( options.filterValue ) > 0 )

// The [nameClause] variable will be replaced as its used in a stmt,


when the table alias is known
checkVal = dbConnect.EscapeValueForLikeClause( options.filterValue )
options.filterEscapedValue = Str.Trim( checkVal.like )

if ( IsPostgreSQL )

options.filterEscapedValue = Str.ReplaceAll( options.filterValue,


"_", "|_" )
typeFilterClause = " AND [nameclause] ILIKE :A1 ESCAPE '|'"

else

typeFilterClause = Str.Format(
" AND [lowernameclause] LIKE LOWER(
:A1 ) ESCAPE '%1'",
checkVal.escapeChar )

end

hasFilter = TRUE

params = { ._LikeFormat( options.filterEscapedValue, options ) }

end

clause.Sql = typeFilterClause
clause.params = params

rtnVal.ok = ok
rtnVal.errMsg = errMsg
rtnVal.apiError = apiError
rtnVal.hasFilter = hasFilter
rtnVal.clause = clause

return rtnVal

end

sEND
f _GetSelectWithPaging_clauseWhere
s
/**
* @private
*
* This method will return various SQL statements needed for browse.
*
* @param {Object} dapiCtx DAPI session object
* @param {DAPINODE} node The browse page node
* @param {String} viewName The database view name
* @param {String} userPrefLanguage The user prefered language
* @param {String} sortField The view column name to sort on
* @param {Assoc} options An assoc containing SQL options. See
{@link _ValidateOptions}
*
* @return {Assoc}
* @returnFeature {Boolean} ok TRUE if ok.
* @returnFeature {String} errMsg Application error message if not ok.
* @returnFeature {Error} apiError Error returned by API if not ok.
* @returnFeature {Boolean} hasFilter Boolean indicating if the query has any
additional filters.
* @returnFeature {Assoc} clause assoc with info about a fragment of a SQL
clause
* @returnFeature* {String} sql SQL fragment
* @returnFeature* {List} params The first element contains the parent ID,
the second (optional) parameter contains filtering data.
*/
function Assoc _GetSelectWithPaging_clauseWhere(
Object dapiCtx,
DAPINODE node,
String viewName,
String userPrefLanguage,
String sortField,
Assoc options )

Assoc clause
Assoc rtnVal
Dynamic apiError
List params
String errMsg
String whereClause

Boolean hasFilter = FALSE


Boolean ok = TRUE

//
// If the caller has sent in where clause then we need to attach it to the
main script.
//

if ( Length( options.whereClause ) > 0 )

whereClause = " AND " + options.whereClause


hasFilter = TRUE

end

clause.Sql = whereClause
clause.params = params

rtnVal.ok = ok
rtnVal.errMsg = errMsg
rtnVal.apiError = apiError
rtnVal.hasFilter = hasFilter
rtnVal.clause = clause

return rtnVal

end
sEND
f _GetSelectWithPaging_stmtMimeCount
s
/**
* @private
*
* Returns a SQL statement needed for target browse in order to limit the displayed
items
* to a specific mime counts.
*
* @param {Object} dapiCtx DAPI session object
* @param {DAPINODE} node The browse page node
* @param {String} viewName The database view name
* @param {String} userPrefLanguage The user prefered language
* @param {String} sortField The view column name to sort on
* @param {Assoc} options An assoc containing SQL options. See
{@link _ValidateOptions}
* @param {Assoc} clause An assoc containing various SQL clause
snippets strings
* @param* {String} hidden A hidden clause string
* @param* {String} where A where clause string
* @param* {String} typeFilter A type filter clause string
* @param* {String} objectFilter A object filter clause string
* @param* {String} containerOnly A container only filter clause string
* @param* {String} mimeFilter A mime filter clause string
* @param* {String} descriptionFilter A description filter clause string
*
* @return {Assoc}
* @returnFeature {Boolean} ok FALSE if an error occurred, TRUE otherwise
* @returnFeature {String} errMsg Error message, if an error occurred
* @returnFeature {Dynamic} apiError Application error, if applicable
* @returnFeature {Assoc} stmt SQL statement
* @returnFeature {List} params bind variables used for this statement
*/
function Assoc _GetSelectWithPaging_stmtMimeCount(
Object dapiCtx,
DAPINODE node,
String viewName,
String userPrefLanguage,
String sortField,
Assoc options,
Assoc clause )

Assoc rtnVal
Dynamic apiError
List params
String errMsg
String mimeCountStmt
String whereString

Boolean ok = TRUE

if ( IsDefined( options.mimeScreen ) && Length( clause.mimeFilter.Sql ) > 0 )

if ( IsDefined( node ) )

whereString = "a.ParentID=:A0 AND a.OwnerID=:A0 "


params = { node.pID, node.pVolumeID }

end
if ( dapiCtx.fDBConnect.IsHana() )

mimeCountStmt = "SELECT COUNT(*) mimeRowCnt FROM (" +


"SELECT a.DataID FROM DTree a INNER JOIN DVersData b ON
a.DataID = b.DocID AND a.VersionNum = b.Version WHERE " +
whereString + " b.VerType IS NULL AND a.Major IS NULL AND "
+ clause.mimeFilter.Sql +
" UNION ALL SELECT a.DataID FROM DTree a INNER JOIN
DVersData b ON a.DataID = b.DocID AND a.Major = b.Version WHERE " +

whereString + " b.VerType IS NULL AND a.Major IS NOT NULL


AND " + clause.mimeFilter.Sql + ")"

params = { @params, @clause.mimeFilter.params }

if ( IsDefined( node ) )

params = { @params, node.pID }

end

else

whereString += "a.DataID = b.DocID AND ( a.Major = b.Version OR (


a.Major IS NULL AND a.VersionNum = b.Version ) ) " +
"AND b.VerType IS NULL AND " + clause.mimeFilter.Sql
mimeCountStmt = "SELECT count(*) mimeRowCnt FROM DTree a,
DVersData b WHERE " + whereString

end

params = { @params, @clause.mimeFilter.params }

end

rtnVal.ok = ok
rtnVal.errMsg = errMsg
rtnVal.apiError = apiError
rtnVal.stmt = mimeCountStmt
rtnVal.params = params

return rtnVal

end
sEND
f fMaxBrowseGulpSize
v 300
f fMaxBrowseGulpSize
v 300
o {'pat162007597::LanguagePkg',&&lliapi::LanguagePkg}
N LanguagePkg
f IsMultilingual
s
/**
* IsMultilingual() will determine whether the Content Server system is
multilingual
* (i.e. has multiple enabled languages).
*
* @param {Object} prgCtx Program session object
*
* @return {Assoc}
* @returnFeature {Boolean} ok FALSE if an error occurred; TRUE
otherwise
* @returnFeature {String} errMsg Error message if an error occurred
* @returnFeature {Dynamic} apiError Application error object if an error
occurred
* @returnFeature {Boolean} isMultilingual TRUE if this is a multilingual system
*/
function Assoc IsMultilingual( Object prgCtx )

Assoc checkVal
Dynamic apiError
Dynamic result
String errMsg

Boolean ok = TRUE
Boolean isMultilingual = FALSE

if ( IsUndefined( .fisMultilingual ) )

result = Language.GetEnabledLanguages( prgCtx.fDbConnect.fConnection )

if ( IsNotError( result ) )

isMultilingual = ( Length( result ) > 1 ) ||


( Length( result ) == 1 &&
.GetDatabaseCollation( prgCtx ) !
= .GetDatabaseCollation( prgCtx, result[1].languageCode ) )

else

ok = FALSE
errMsg = [LLIAPI_ERRMSG.CouldNotGetEnabledLanguages]
apiError = result

end

.fisMultilingual = isMultilingual

end

return Assoc{
'ok': ok,
'errMsg': errMsg,
'apiError': apiError,
'isMultilingual': .fisMultilingual }

end
sEND
f fisMultilingual
v ?
f fisMultilingual
v ?
o {'pat162007597::Classification DocVolume',&&webclassification::#'Classification
DocVolume'#}
N Classification DocVolume
f _BrowseContents
s

function void _BrowseContents( \


Object prgCtx, \
Dynamic request, \
Dynamic response )

Dynamic checkVal
RecArray contents
Assoc options
Assoc result
Integer i
Integer pageSize
Integer pstageID
RecArray stagingContents
Assoc retVal
String viewName
Assoc sectionData
String exclusionClause
String alias

Assoc KiniSettings = $AdminUtils.GetNavConfigSettings( prgCtx,


request.CookieData )
DAPINode node = request.node
Object llNode = .LLNode()
String screenClause = Undefined

Boolean allContents = ( RecArray.IsColumn( request,


"_allContents" ) != 0 )
Boolean hasStagedContent = FALSE
Boolean ok = TRUE
Boolean isMultilingual = $LLIAPI.LanguagePkg.IsMultilingual( prgCtx
).isMultilingual

Object webNodes = $WebNode.WebNodes

if ( allContents )

alias = ""

elseif ( isMultilingual )

alias = "dt."

elseif ( !isMultilingual )

alias = "wnm."

end

if ( RecArray.IsColumn( request, "objAction" ) &&


( Str.CmpI( request.objAction, 'targetbrowse' ) == 0 ||
Str.CmpI( request.objAction, 'browse' ) == 0 ))
// targetbrowse and browse action of the classification volume, exclude
hidden objects

exclusionClause = 'Catalog!=2'
exclusionClause += Str.Format(" AND %1SubType!=296 ",alias )
else
// this can be 'editconfig' action where we want to show hidden objects

exclusionClause =Str.Format( " %1SubType!=296 ", alias )

end

// Determine node screen clause


if ( RecArray.IsColumn( request, "nodeScreen" ) )

for i in request.nodeScreen

if ( IsUndefined( screenClause ) )

screenClause = "SubType=" + Str.String( i )


else
screenClause += " or SubType=" + Str.String( i )
end
end

screenClause = Str.Format( '%1 and %2', screenClause, exclusionClause )

else
if ( IsUndefined( screenClause ) )

screenClause = exclusionClause

end
end

// Set up the options needed to get the node contents


options = .GetListContentsByPageOptions( request, screenClause )
options.forcePagination=FALSE
options.useNodeListContents=1
//
// Allow the request to override the maximum number of results per page
//
if ( allContents )

// Set up the viewName variable to be multilingual


checkVal = $LLIApi.LanguagePkg.GetMultilingualViewName( prgCtx,
'WebNodes' )

if ( checkVal.ok == TRUE )

viewName = checkVal.viewName

else
ok = FALSE
response.error = checkVal.errMsg
end

if ( ok )

result = LLNode.NodeListContents( node, \


viewName, \
options.whereClause, \
options.permissionsMask )
end
else

if ( IsFeature( request, "pageSize" ) &&


IsDefined( request.pageSize ) )

pageSize = request.pageSize

else

pageSize = KiniSettings.defaultPageSize
end

result = llNode.NodeListContentsByPage( node, \


request.page, \
pageSize, \
.GetSortOnColumn( request ), \
options )
end

if ( ok && ._IsNotError( prgCtx.fDBConnect, result, response.error,


[WebNode_ErrMsg.ErrorGettingTheSpecifiedObjectSContents] ) )

contents = result.contents

//
// save data for display if it exists
//

if ( IsFeature( result, "totalCount" ) )

response.data.totalCount = result.totalCount
else

response.data.totalCount = Length( result.contents )


end
if ( IsFeature( result, "pages" ) )

response.data.pages = result.pages
end

if ( IsFeature( result, "types" ) )

response.data.types = result.types
end

if ( IsFeature( request, "page" ) )

response.data.page = request.page
else
response.data.page = 1
end

if IsDefined( $PStage )

if ( request.viewType ==
Str.ValueToString( $ViewTypeStagedContent ) )
response.webScript
= .HTMLFile( 'BrowseBaseStaged', .fHTMLBrowseBaseStaged )
response.data.view
= .HTMLFile( 'BrowseStaged', .fHTMLBrowseStaged )
end

retVal = $pstage.utils.MaybeGetStagingFolder( prgCtx, node )

if ( retVal.ok && IsDefined( retVal.folder ) )

pstageID = node.pID
node = retVal.folder

// Get the staged contents.


if ( RecArray.IsColumn( request, "nodeScreen" ) )

stagingContents =
DAPI.ListContents( prgCtx.DapiSess(), \
node.pVolumeId, \
node.pId, \
"WebNodes", \
screenClause, \
$PSee )
else
stagingContents =
DAPI.ListContents( prgCtx.DapiSess(), \
node.pVolumeId, \
node.pId, \
"WebNodes" )
end

if ( ._IsNotError( prgCtx.fDBConnect, stagingContents,


response.error, [WebNode_ErrMsg.ErrorGettingTheSpecifiedObjectSContents] ) )

if ( Length( stagingContents ) > 0 )

hasStagedContent = true

if ( request.viewType ==
Str.ValueToString( $ViewTypeStagedContent ) )

for i = 1 to Length( stagingContents )

RecArray.AddRecord( contents,
RecArray.GetRecord( stagingContents, i ) )
end
end
end
end
end
end

response.data.contents = contents

if ( hasStagedContent )

response.data.hasStagedContent = true
response.data.stagedContent = stagingContents
response.data.pstageID = pstageID
end

// Set the catalog title


response.data.catalogTitle =
[WebClassification_HTMLLabel.FeaturedClassificationTrees]

// Set the list title


response.data.listTitle = [WebClassification_Label.Classifications]

// Set the classified objects title

response.data.objectsTitle =
[WebClassification_HTMLLabel.ClassifiedItems]

// Setup the data for the call to the ClassifiedItems virtual webnode
// The virtual webnode is used to allow the "Classifications" and
"Classified Items" sections to sort independently.
sectionData = Assoc.CreateAssoc()

sectionData.webnode = webNodes.GetItem( 194 )

sectionData.parm = .SetupParmAssoc( request, prgCtx )


sectionData.action = "Action-Browse"

response.data.SectionData = sectionData

end
end

sEND

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy