getHistoryPermissionAndUser($page_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 u.Username END FROM ' . $this->Application->getUnitOption('page-revision', 'TableName') . ' pr LEFT JOIN ' . TABLE_PREFIX . 'PortalUser u ON u.PortalUserId = pr.CreatedById WHERE (' . implode(') AND (', $where_clause) . ')'; $users = $this->Conn->GetCol($sql); $page_revisions = Array (); if ( $history_permission ) { $tag_params = Array ('per_page' => -1, 'skip_parent_filter' => 1, 'requery' => 1, 'page_id' => $page_id); $revisions =& $this->Application->recallObject('page-revision.list', 'page-revision_List', $tag_params); /* @var $revisions kDBList */ $revisions->Query(); $revisions->GoFirst(); $status_options = $revisions->GetFieldOptions('Status'); $draft_label = $this->Application->Phrase('la_Draft', false, true); $title_label = $this->Application->Phrase('la_RevisionNumber', false, true); $by_label = $this->Application->Phrase('la_By', false, true); while ( !$revisions->EOL() ) { $status = $revisions->GetDBField('Status'); $status_label = $this->Application->Phrase($status_options['options'][$status], false, true); $page_revisions[ 'r' . $revisions->GetDBField('RevisionNumber') ] = Array ( 'title' => $revisions->GetDBField('IsDraft') ? $draft_label : sprintf($title_label, $revisions->GetDBField('RevisionNumber')), 'status' => $status, 'status_label' => mb_strtolower($status_label), 'datetime' => $revisions->GetField('CreatedOn'), 'author' => $by_label . ': ' . $revisions->GetField('CreatedById'), 'draft' => (int)$revisions->GetDBField('IsDraft'), ); $revisions->GoNext(); } } $current_revision =& $this->Application->recallObject('page-revision.current'); /* @var $current_revision kDBItem */ $revision_status = $current_revision->GetDBField('Status'); $status_options = $current_revision->GetFieldOptions('Status'); $status_label = $this->Application->Phrase($status_options['options'][$revision_status], false, true); $revision_phase = $current_revision->GetDBField('IsDraft') ? 'la_title_EditingDraft' : 'la_title_ViewingRevision'; $revision_title = sprintf($this->Application->Phrase($revision_phase, false, true), $current_revision->GetDBField('RevisionNumber'), mb_strtolower($status_label)); $current_revision_info = Array ('title' => $revision_title, 'status' => $revision_status, 'saved' => ''); $autosave_time = $current_revision->GetDBField('AutoSavedOn'); if ( $autosave_time ) { $phrase = $this->Application->Phrase($current_revision->GetDBField('IsDraft') ? 'la_DraftSavedAt' : 'la_SavedAt', false, true); $current_revision_info['saved'] = sprintf($phrase, $current_revision->GetField('AutoSavedOn_time') . ' (' . $this->getAgoTime($autosave_time) . ')'); } $currently_editing = $this->getPluralPhrase( count($users), Array ( 'phrase1' => 'la_PageCurrentlyEditing1', 'phrase2' => 'la_PageCurrentlyEditing2', 'phrase5' => 'la_PageCurrentlyEditing5', ), false, true ); $currently_editing = sprintf($currently_editing, implode(', ', $users)); return Array ('current_revision' => $current_revision_info, 'editors' => $users, 'editors_warning' => $currently_editing, 'revisions' => $page_revisions); } /** * Returns time passed between 2 given dates in "X minutes Y seconds ago" format * * @param int $from_date * @param int $to_date * @return string */ 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 */ 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->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; } /** * Returns current admin user id (even, when called from front-end) and it's revision history view permission * * @param int $page_id * @return Array */ function getHistoryPermissionAndUser($page_id) { $user_id = (int)$this->Application->RecallVar($this->Application->isAdmin ? 'user_id' : 'admin_user_id'); $history_permission = $this->Application->CheckAdminPermission('CATEGORY.REVISION.HISTORY.VIEW', 0, $page_id); return Array ($user_id, $history_permission); } /** * Creates new content block in every revision that misses it. Plus creates first page revision * * @param int $page_id * @param int $num */ 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 $revision =& $this->Application->recallObject('page-revision.live', null, Array ('skip_autoload' => true)); /* @var $revision kDBItem */ $revision->SetDBField('PageId', $page_id); $revision->SetDBField('RevisionNumber', 1); $revision->SetDBField('Status', STATUS_ACTIVE); $revision->Create(); $revisions[ $revision->GetID() ] = NULL; } $content_block =& $this->Application->recallObject('content.new', null, Array ('skip_autoload' => true)); /* @var $content_block kDBItem */ $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 */ function loadContentBlock(&$content_block, &$page, $num) { $page_id = $page->GetID(); if ( !EDITING_MODE && !$this->Application->GetVar('preview') ) { $revision_clause = 'pr.RevisionNumber = ' . $page->GetDBField('LiveRevisionNumber') . ' AND pr.IsDraft = 0'; } else { $revision_clause = $this->getRevsionWhereClause($page_id, $page->GetDBField('LiveRevisionNumber'), 'pr.'); } $sql = $content_block->GetSelectSQL() . ' WHERE (' . $content_block->TableName . '.PageId = ' . $page_id . ') AND (' . $content_block->TableName . '.ContentNum = ' . $num . ') AND (' . $revision_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 phrase based on given number * * @param int $number * @param Array $forms * @return string */ function getPluralPhrase($number, $forms, $allow_editing = true, $use_admin = false) { // normalize given forms if ( !array_key_exists('phrase5', $forms) ) { $forms['phrase5'] = $forms['phrase2']; } $phrase_type = $this->getPluralPhraseType($number); return $this->Application->Phrase( $forms['phrase' . $phrase_type], $allow_editing, $use_admin ); } /** * Returns phrase type based on given number * * @param int $number * @return int */ function getPluralPhraseType($number) { $last_digit = substr($number, -1); $last_but_one_digit = strlen($number) > 1 ? substr($number, -2, 1) : false; $phrase_type = '5'; if ($last_but_one_digit != 1) { if ($last_digit == 1) { $phrase_type = '1'; } elseif ($last_digit >= 2 && $last_digit <= 4) { $phrase_type = '2'; } } return $phrase_type; } }