Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1102277
page_helper.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
Mon, Aug 18, 3:11 PM
Size
14 KB
Mime Type
text/x-php
Expires
Wed, Aug 20, 3:11 PM (1 d, 3 h)
Engine
blob
Format
Raw Data
Handle
714061
Attached To
rINP In-Portal
page_helper.php
View Options
<?php
/**
* @version $Id: page_helper.php 16667 2021-01-15 15:06:47Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 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
PageHelper
extends
kHelper
{
/**
* Content block cache per page.
*
* @var array
*/
protected
$contentBlockCache
=
array
();
/**
* Returns page info
*
* @param int $page_id
* @return Array
*/
function
getPageInfo
(
$page_id
)
{
list
(
$user_id
,
$history_permission
)
=
$this
->
getHistoryPermissionAndUser
(
$page_id
);
$users
=
$this
->
getEditors
(
$page_id
,
$user_id
);
return
array
(
'current_revision'
=>
$this
->
getCurrentRevisionInfo
(),
'editors'
=>
$users
,
'editors_warning'
=>
$this
->
getEditorsWarning
(
$users
),
'revisions'
=>
$history_permission
?
$this
->
getPageRevisions
(
$page_id
)
:
array
(),
);
}
/**
* Returns current admin user id (even, when called from front-end) and it's revision history view permission
*
* @param int $page_id
* @return Array
*/
protected
function
getHistoryPermissionAndUser
(
$page_id
)
{
/** @var kPermissionsHelper $perm_helper */
$perm_helper
=
$this
->
Application
->
recallObject
(
'PermissionsHelper'
);
$user_id
=
(
int
)
$this
->
Application
->
RecallVar
(
$this
->
Application
->
isAdmin
?
'user_id'
:
'admin_user_id'
);
$history_permission
=
$perm_helper
->
CheckUserPermission
(
$user_id
,
'CATEGORY.REVISION.HISTORY.VIEW'
,
0
,
$page_id
);
return
Array
(
$user_id
,
$history_permission
);
}
/**
* Returns information about given page editors.
*
* @param integer $page_id Page, that is being edited.
* @param integer $user_id User, who is editing a page.
*
* @return array
*/
protected
function
getEditors
(
$page_id
,
$user_id
)
{
$where_clause
=
array
(
'pr.PageId = '
.
$page_id
,
'pr.CreatedById <> '
.
$user_id
,
'pr.IsDraft = 1'
,
);
$sql
=
'SELECT CASE pr.CreatedById WHEN '
.
USER_ROOT
.
' THEN "root" WHEN '
.
USER_GUEST
.
' THEN "Guest" ELSE IF(u.Username = "", u.Email, u.Username) END
FROM '
.
$this
->
Application
->
getUnitOption
(
'page-revision'
,
'TableName'
)
.
' pr
LEFT JOIN '
.
TABLE_PREFIX
.
'Users u ON u.PortalUserId = pr.CreatedById
WHERE ('
.
implode
(
') AND ('
,
$where_clause
)
.
')'
;
return
$this
->
Conn
->
GetCol
(
$sql
);
}
/**
* Returns information about current revision.
*
* @return array
*/
protected
function
getCurrentRevisionInfo
()
{
/** @var kDBItem $revision */
$revision
=
$this
->
Application
->
recallObject
(
'page-revision.current'
);
$status_label
=
$this
->
getRevisionStatusText
(
$revision
);
$draft
=
$revision
->
GetDBField
(
'IsDraft'
);
$title
=
$this
->
getAdminPhrase
(
$draft
?
'la_title_EditingDraft'
:
'la_title_ViewingRevision'
);
$current_revision_info
=
array
(
'title'
=>
sprintf
(
$title
,
$revision
->
GetDBField
(
'RevisionNumber'
),
$status_label
),
'status'
=>
$revision
->
GetDBField
(
'Status'
),
'saved'
=>
''
,
'toolbar_state'
=>
$this
->
getToolbarButtonsState
(
$revision
),
);
$auto_save_time
=
$revision
->
GetDBField
(
'AutoSavedOn'
);
if
(
$auto_save_time
)
{
$phrase
=
$this
->
getAdminPhrase
(
$draft
?
'la_DraftSavedAt'
:
'la_SavedAt'
);
$current_revision_info
[
'saved'
]
=
sprintf
(
$phrase
,
$revision
->
GetField
(
'AutoSavedOn_time'
)
.
' ('
.
$this
->
getAgoTime
(
$auto_save_time
)
.
')'
);
}
return
$current_revision_info
;
}
/**
* Returns state of all CMS revision toolbar buttons.
*
* @param kDBItem $revision Page Revision.
*
* @return array
*/
public
function
getToolbarButtonsState
(
kDBItem
$revision
)
{
$ret
=
array
();
foreach
(
$this
->
getToolbarButtons
()
as
$toolbar_button
)
{
$ret
[
$toolbar_button
]
=
$this
->
isToolbarButtonEnabled
(
$toolbar_button
,
$revision
);
}
return
$ret
;
}
/**
* Returns list of CMS revision toolbar buttons.
*
* @return array
*/
protected
function
getToolbarButtons
()
{
return
array
(
'select'
,
'delete'
,
'approve'
,
'decline'
,
'preview'
,
'history'
);
}
/**
* Checks if given CMS revision toolbar button is enabled for given revision.
*
* @param string $button_name Toolbar button name.
* @param kDBItem $revision Revision to check against.
*
* @return boolean
*/
protected
function
isToolbarButtonEnabled
(
$button_name
,
kDBItem
$revision
)
{
$is_draft
=
$revision
->
GetDBField
(
'IsDraft'
);
if
(
$button_name
==
'select'
||
$button_name
==
'delete'
||
$button_name
==
'preview'
)
{
return
(
bool
)
$is_draft
;
}
if
(
$button_name
==
'approve'
)
{
return
$revision
->
GetDBField
(
'Status'
)
!=
STATUS_ACTIVE
&&
!
$is_draft
;
}
if
(
$button_name
==
'decline'
)
{
return
$revision
->
GetDBField
(
'Status'
)
!=
STATUS_DISABLED
&&
!
$revision
->
GetDBField
(
'IsLive'
)
&&
!
$is_draft
;
}
return
true
;
}
/**
* Returns warning to be shown in case of parallel editing attempts.
*
* @param array $users Users, that are editing a page.
*
* @return string
*/
protected
function
getEditorsWarning
(
array
$users
)
{
/** @var kMultiLanguageHelper $ml_helper */
$ml_helper
=
$this
->
Application
->
recallObject
(
'kMultiLanguageHelper'
);
$ret
=
$ml_helper
->
getPluralPhrase
(
count
(
$users
),
array
(
'phrase1'
=>
'la_PageCurrentlyEditing1'
,
'phrase2'
=>
'la_PageCurrentlyEditing2'
,
'phrase5'
=>
'la_PageCurrentlyEditing5'
,
),
false
,
true
);
return
sprintf
(
$ret
,
implode
(
', '
,
$users
));
}
/**
* Returns information about given page revisions.
*
* @param integer $page_id Page, that is being edited.
*
* @return array
*/
protected
function
getPageRevisions
(
$page_id
)
{
$ret
=
Array
();
$tag_params
=
Array
(
'per_page'
=>
-
1
,
'skip_parent_filter'
=>
1
,
'requery'
=>
1
,
'page_id'
=>
$page_id
);
/** @var kDBList $revisions */
$revisions
=
$this
->
Application
->
recallObject
(
'page-revision.list'
,
'page-revision_List'
,
$tag_params
);
$revisions
->
Query
();
$revisions
->
GoFirst
();
while
(
!
$revisions
->
EOL
()
)
{
$ret
[
'r'
.
$revisions
->
GetDBField
(
'RevisionNumber'
)
]
=
array
(
'title'
=>
$this
->
getRevisionTitle
(
$revisions
),
'status'
=>
$revisions
->
GetDBField
(
'Status'
),
'status_label'
=>
$this
->
getRevisionStatusText
(
$revisions
),
'datetime'
=>
$revisions
->
GetField
(
'CreatedOn'
),
'author'
=>
$this
->
getRevisionAuthor
(
$revisions
),
'draft'
=>
(
int
)
$revisions
->
GetDBField
(
'IsDraft'
),
);
$revisions
->
GoNext
();
}
return
$ret
;
}
/**
* Returns title for given revision.
*
* @param kDBBase $revision Page Revision.
*
* @return string
*/
protected
function
getRevisionTitle
(
kDBBase
$revision
)
{
if
(
$revision
->
GetDBField
(
'IsDraft'
)
)
{
return
$this
->
getAdminPhrase
(
'la_Draft'
);
}
$title
=
$this
->
getAdminPhrase
(
'la_RevisionNumber'
);
return
sprintf
(
$title
,
$revision
->
GetDBField
(
'RevisionNumber'
));
}
/**
* Returns status text for given revision.
*
* @param kDBBase $revision Page Revision.
*
* @return string
*/
protected
function
getRevisionStatusText
(
kDBBase
$revision
)
{
$status
=
$revision
->
GetDBField
(
'Status'
);
$options
=
$revision
->
GetFieldOptions
(
'Status'
);
return
mb_strtolower
(
$this
->
getAdminPhrase
(
$options
[
'options'
][
$status
]));
}
/**
* Returns author of given revision.
*
* @param kDBBase $revision Page Revision.
*
* @return string
*/
protected
function
getRevisionAuthor
(
kDBBase
$revision
)
{
$by_label
=
$this
->
getAdminPhrase
(
'la_By'
);
return
$by_label
.
': '
.
$revision
->
GetField
(
'CreatedById'
);
}
/**
* Returns Admin's non-editable translation of given phrase.
*
* @param string $label Phrase label.
*
* @return string
*/
protected
function
getAdminPhrase
(
$label
)
{
return
$this
->
Application
->
Phrase
(
$label
,
false
,
true
);
}
/**
* Returns time passed between 2 given dates in "X minutes Y seconds ago" format
*
* @param int $from_date
* @param int $to_date
* @param integer $max_levels
*
* @return string
*/
public
function
getAgoTime
(
$from_date
,
$to_date
=
null
,
$max_levels
=
1
)
{
$blocks
=
Array
(
Array
(
'name'
=>
'year'
,
'amount'
=>
60
*
60
*
24
*
365
),
Array
(
'name'
=>
'month'
,
'amount'
=>
60
*
60
*
24
*
31
),
Array
(
'name'
=>
'week'
,
'amount'
=>
60
*
60
*
24
*
7
),
Array
(
'name'
=>
'day'
,
'amount'
=>
60
*
60
*
24
),
Array
(
'name'
=>
'hour'
,
'amount'
=>
60
*
60
),
Array
(
'name'
=>
'minute'
,
'amount'
=>
60
),
Array
(
'name'
=>
'second'
,
'amount'
=>
1
),
);
if
(
!
isset
(
$to_date
)
)
{
$to_date
=
adodb_mktime
();
}
$diff
=
abs
(
$to_date
-
$from_date
);
if
(
$diff
==
0
)
{
return
'now'
;
}
$current_level
=
1
;
$result
=
Array
();
foreach
(
$blocks
as
$block
)
{
if
(
$current_level
>
$max_levels
)
{
break
;
}
if
(
$diff
/
$block
[
'amount'
]
>=
1
)
{
$amount
=
floor
(
$diff
/
$block
[
'amount'
]);
$plural
=
$amount
>
1
?
's'
:
''
;
$result
[]
=
$amount
.
' '
.
$block
[
'name'
]
.
$plural
;
$diff
-=
$amount
*
$block
[
'amount'
];
$current_level
++;
}
}
return
implode
(
' '
,
$result
)
.
' ago'
;
}
/**
* Returns where clause for loading correct revision for a given page
*
* @param int $page_id
* @param int $live_revision_number
* @param string $table_name
* @return string
*/
public
function
getRevsionWhereClause
(
$page_id
,
$live_revision_number
,
$table_name
=
''
)
{
$revision
=
(
int
)
$this
->
Application
->
GetVar
(
'revision'
);
list
(
$user_id
,
$has_permission
)
=
$this
->
getHistoryPermissionAndUser
(
$page_id
);
if
(
$has_permission
&&
$revision
)
{
$revision_clause
=
$table_name
.
'RevisionNumber = '
.
$revision
.
' AND '
.
$table_name
.
'IsDraft = 0'
;
}
else
{
$editing_mode
=
$this
->
Application
->
GetVar
(
'editing_mode'
);
// not in a EDITING_MODE constant, while in admin console
$revision_clause
=
$table_name
.
'RevisionNumber = '
.
$live_revision_number
.
' AND '
.
$table_name
.
'IsDraft = 0'
;
if
(
$this
->
Application
->
ConfigValue
(
'EnablePageContentRevisionControl'
)
)
{
if
(
$this
->
Application
->
GetVar
(
'preview'
)
||
$editing_mode
==
EDITING_MODE_CONTENT
)
{
$revision_clause
=
'('
.
$table_name
.
'CreatedById = '
.
$user_id
.
' AND '
.
$table_name
.
'IsDraft = 1) OR ('
.
$revision_clause
.
')'
;
}
}
}
return
$revision_clause
;
}
/**
* Creates new content block in every revision that misses it. Plus creates first page revision
*
* @param int $page_id
* @param int $num
*/
public
function
createNewContentBlock
(
$page_id
,
$num
)
{
$sql
=
'SELECT pc.PageContentId, pr.RevisionId
FROM '
.
TABLE_PREFIX
.
'PageRevisions pr
LEFT JOIN '
.
TABLE_PREFIX
.
'PageContent pc ON pc.RevisionId = pr.RevisionId AND pc.ContentNum = '
.
$num
.
'
WHERE pr.PageId = '
.
$page_id
;
$revisions
=
$this
->
Conn
->
GetCol
(
$sql
,
'RevisionId'
);
if
(
!
$revisions
)
{
// no revisions for a page -> create a live revision
/** @var kDBItem $revision */
$revision
=
$this
->
Application
->
recallObject
(
'page-revision.live'
,
null
,
Array
(
'skip_autoload'
=>
true
));
$revision
->
SetDBField
(
'PageId'
,
$page_id
);
$revision
->
SetDBField
(
'RevisionNumber'
,
1
);
$revision
->
SetDBField
(
'Status'
,
STATUS_ACTIVE
);
$revision
->
Create
();
$revisions
[
$revision
->
GetID
()
]
=
NULL
;
}
/** @var kDBItem $content_block */
$content_block
=
$this
->
Application
->
recallObject
(
'content.new'
,
null
,
Array
(
'skip_autoload'
=>
true
));
$content_block
->
SetDBField
(
'PageId'
,
$page_id
);
$content_block
->
SetDBField
(
'ContentNum'
,
$num
);
foreach
(
$revisions
as
$revision_id
=>
$content_block_id
)
{
if
(
is_numeric
(
$content_block_id
)
)
{
continue
;
}
$content_block
->
SetDBField
(
'RevisionId'
,
$revision_id
);
$content_block
->
Create
();
}
}
/**
* Loads content block by it's number
*
* @param kDBItem $content_block
* @param CategoriesItem $page
* @param int $num
*
* @return bool
*/
public
function
loadContentBlock
(&
$content_block
,
&
$page
,
$num
)
{
$page_id
=
$page
->
GetID
();
// Load all content blocks at once during regular page visits.
if
(
!
EDITING_MODE
&&
!
$this
->
Application
->
GetVar
(
'preview'
)
)
{
if
(
!
isset
(
$this
->
contentBlockCache
[
$page_id
])
)
{
$where_clause
=
array
(
$content_block
->
TableName
.
'.PageId = '
.
$page_id
,
'pr.RevisionNumber = '
.
$page
->
GetDBField
(
'LiveRevisionNumber'
),
'pr.IsDraft = 0'
,
);
$sql
=
$content_block
->
GetSelectSQL
()
.
'
WHERE ('
.
implode
(
') AND ('
,
$where_clause
)
.
')'
;
$this
->
contentBlockCache
[
$page_id
]
=
$this
->
Conn
->
Query
(
$sql
,
'ContentNum'
);
}
if
(
isset
(
$this
->
contentBlockCache
[
$page_id
][
$num
])
)
{
$content_block
->
LoadFromHash
(
$this
->
contentBlockCache
[
$page_id
][
$num
]);
}
else
{
$content_block
->
Clear
();
}
return
$content_block
->
isLoaded
();
}
// Load each content block individually with fallback to draft version, when editing content.
$where_clause
=
array
(
$content_block
->
TableName
.
'.PageId = '
.
$page_id
,
$content_block
->
TableName
.
'.ContentNum = '
.
$num
,
$this
->
getRevsionWhereClause
(
$page_id
,
$page
->
GetDBField
(
'LiveRevisionNumber'
),
'pr.'
),
);
$sql
=
$content_block
->
GetSelectSQL
()
.
'
WHERE ('
.
implode
(
') AND ('
,
$where_clause
)
.
')
ORDER BY pr.IsDraft DESC, pr.RevisionNumber DESC'
;
$content_data
=
$this
->
Conn
->
GetRow
(
$sql
);
$content_block
->
LoadFromHash
(
$content_data
);
return
$content_block
->
isLoaded
();
}
/**
* Returns revision content
*
* @param integer $page_revision_id Page revision Id.
*
* @return array
*/
public
function
getRevisionContent
(
$page_revision_id
)
{
$sql
=
'SELECT *
FROM '
.
TABLE_PREFIX
.
'PageContent
WHERE RevisionId = '
.
$page_revision_id
;
$blocks
=
$this
->
Conn
->
GetIterator
(
$sql
);
/** @var kMultiLanguageHelper $ml_helper */
$ml_helper
=
$this
->
Application
->
recallObject
(
'kMultiLanguageHelper'
);
$content
=
array
();
foreach
(
$ml_helper
->
getLanguages
()
as
$lang_id
)
{
$parts
=
array
();
foreach
(
$blocks
as
$block_data
)
{
if
(
(
string
)
$block_data
[
'l'
.
$lang_id
.
'_Content'
]
!==
''
)
{
$parts
[]
=
$this
->
makeSearchable
(
$block_data
[
'l'
.
$lang_id
.
'_Content'
]);
}
}
$content
[
'l'
.
$lang_id
.
'_PageContent'
]
=
implode
(
' '
,
$parts
);
}
return
$content
;
}
/**
* Unescapes and removes tags
*
* @param string $content Content.
*
* @return string
*/
protected
function
makeSearchable
(
$content
)
{
return
trim
(
strip_tags
(
html_entity_decode
(
$content
,
ENT_QUOTES
,
'UTF-8'
)));
}
}
Event Timeline
Log In to Comment