first commit
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Controller;
|
||||
|
||||
use Drupal\comment\CommentStatisticsInterface;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Database\Query\PagerSelectExtender;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Controller for tracker pages.
|
||||
*/
|
||||
class TrackerController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The database connection.
|
||||
*
|
||||
* @var \Drupal\Core\Database\Connection
|
||||
*/
|
||||
protected $database;
|
||||
|
||||
/**
|
||||
* The database replica connection.
|
||||
*
|
||||
* @var \Drupal\Core\Database\Connection
|
||||
*/
|
||||
protected $databaseReplica;
|
||||
|
||||
/**
|
||||
* The comment statistics.
|
||||
*
|
||||
* @var \Drupal\comment\CommentStatisticsInterface
|
||||
*/
|
||||
protected $commentStatistics;
|
||||
|
||||
/**
|
||||
* The date formatter.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
/**
|
||||
* The node storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $nodeStorage;
|
||||
|
||||
/**
|
||||
* Constructs a TrackerController object.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $database
|
||||
* The database connection.
|
||||
* @param \Drupal\Core\Database\Connection $databaseReplica
|
||||
* The database replica connection.
|
||||
* @param \Drupal\comment\CommentStatisticsInterface $commentStatistics
|
||||
* The comment statistics.
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter
|
||||
* The date formatter.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(Connection $database, Connection $databaseReplica, CommentStatisticsInterface $commentStatistics, DateFormatterInterface $dateFormatter, EntityTypeManagerInterface $entityTypeManager) {
|
||||
$this->database = $database;
|
||||
$this->databaseReplica = $databaseReplica;
|
||||
$this->commentStatistics = $commentStatistics;
|
||||
$this->dateFormatter = $dateFormatter;
|
||||
$this->entityTypeManager = $entityTypeManager;
|
||||
$this->nodeStorage = $entityTypeManager->getStorage('node');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('database'),
|
||||
$container->get('database.replica'),
|
||||
$container->get('comment.statistics'),
|
||||
$container->get('date.formatter'),
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Title callback for the tracker.user_tab route.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $user
|
||||
* The user.
|
||||
*
|
||||
* @return string
|
||||
* The title.
|
||||
*/
|
||||
public function getTitle(UserInterface $user) {
|
||||
return $user->getDisplayName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks access for the users recent content tracker page.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $user
|
||||
* The user being viewed.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account viewing the page.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResult
|
||||
* The access result.
|
||||
*/
|
||||
public function checkAccess(UserInterface $user, AccountInterface $account) {
|
||||
return AccessResult::allowedIf($account->isAuthenticated() && $user->id() == $account->id())
|
||||
->cachePerUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds content for the tracker controllers.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface|null $user
|
||||
* (optional) The user account.
|
||||
*
|
||||
* @return array
|
||||
* The render array.
|
||||
*/
|
||||
public function buildContent(UserInterface $user = NULL) {
|
||||
if ($user) {
|
||||
$query = $this->database->select('tracker_user', 't')
|
||||
->extend(PagerSelectExtender::class)
|
||||
->addMetaData('base_table', 'tracker_user')
|
||||
->condition('t.uid', $user->id());
|
||||
}
|
||||
else {
|
||||
$query = $this->databaseReplica->select('tracker_node', 't')
|
||||
->extend(PagerSelectExtender::class)
|
||||
->addMetaData('base_table', 'tracker_node');
|
||||
}
|
||||
|
||||
// This array acts as a placeholder for the data selected later
|
||||
// while keeping the correct order.
|
||||
$tracker_data = $query
|
||||
->addTag('node_access')
|
||||
->fields('t', ['nid', 'changed'])
|
||||
->condition('t.published', 1)
|
||||
->orderBy('t.changed', 'DESC')
|
||||
->limit(25)
|
||||
->execute()
|
||||
->fetchAllAssoc('nid');
|
||||
|
||||
$cacheable_metadata = new CacheableMetadata();
|
||||
$rows = [];
|
||||
if (!empty($tracker_data)) {
|
||||
// Load nodes into an array with the same order as $tracker_data.
|
||||
/** @var \Drupal\node\NodeInterface[] $nodes */
|
||||
$nodes = $this->nodeStorage->loadMultiple(array_keys($tracker_data));
|
||||
|
||||
// Enrich the node data.
|
||||
$result = $this->commentStatistics->read($nodes, 'node', FALSE);
|
||||
foreach ($result as $statistics) {
|
||||
// The node ID may not be unique; there can be multiple comment fields.
|
||||
// Make comment_count the total of all comments.
|
||||
$nid = $statistics->entity_id;
|
||||
if (empty($nodes[$nid]->comment_count)
|
||||
|| !is_numeric($tracker_data[$nid]->comment_count)) {
|
||||
$tracker_data[$nid]->comment_count = $statistics->comment_count;
|
||||
}
|
||||
else {
|
||||
$tracker_data[$nid]->comment_count += $statistics->comment_count;
|
||||
}
|
||||
// Make the last comment timestamp reflect the latest comment.
|
||||
if (!isset($tracker_data[$nid]->last_comment_timestamp)) {
|
||||
$tracker_data[$nid]->last_comment_timestamp = $statistics->last_comment_timestamp;
|
||||
}
|
||||
else {
|
||||
$tracker_data[$nid]->last_comment_timestamp = max($tracker_data[$nid]->last_comment_timestamp, $statistics->last_comment_timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
// Display the data.
|
||||
foreach ($nodes as $node) {
|
||||
// Set the last activity time from tracker data. This also takes into
|
||||
// account comment activity, so getChangedTime() is not used.
|
||||
$last_activity = $tracker_data[$node->id()]->changed;
|
||||
|
||||
$owner = $node->getOwner();
|
||||
$row = [
|
||||
'type' => node_get_type_label($node),
|
||||
'title' => [
|
||||
'data' => [
|
||||
'#type' => 'link',
|
||||
'#url' => $node->toUrl(),
|
||||
'#title' => $node->getTitle(),
|
||||
],
|
||||
'data-history-node-id' => $node->id(),
|
||||
'data-history-node-timestamp' => $node->getChangedTime(),
|
||||
],
|
||||
'author' => [
|
||||
'data' => [
|
||||
'#theme' => 'username',
|
||||
'#account' => $owner,
|
||||
],
|
||||
],
|
||||
'comments' => [
|
||||
'class' => ['comments'],
|
||||
'data' => $tracker_data[$node->id()]->comment_count ?? 0,
|
||||
'data-history-node-last-comment-timestamp' => $tracker_data[$node->id()]->last_comment_timestamp ?? 0,
|
||||
],
|
||||
'last updated' => [
|
||||
'data' => t('@time ago', [
|
||||
'@time' => $this->dateFormatter->formatTimeDiffSince($last_activity),
|
||||
]),
|
||||
],
|
||||
];
|
||||
|
||||
$rows[] = $row;
|
||||
|
||||
// Add node and node owner to cache tags.
|
||||
$cacheable_metadata->addCacheTags($node->getCacheTags());
|
||||
if ($owner) {
|
||||
$cacheable_metadata->addCacheTags($owner->getCacheTags());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the list cache tag for nodes.
|
||||
$cacheable_metadata->addCacheTags($this->nodeStorage->getEntityType()->getListCacheTags());
|
||||
|
||||
$page['tracker'] = [
|
||||
'#rows' => $rows,
|
||||
'#header' => [
|
||||
$this->t('Type'),
|
||||
$this->t('Title'),
|
||||
$this->t('Author'),
|
||||
$this->t('Comments'),
|
||||
$this->t('Last updated'),
|
||||
],
|
||||
'#type' => 'table',
|
||||
'#empty' => $this->t('No content available.'),
|
||||
];
|
||||
$page['pager'] = [
|
||||
'#type' => 'pager',
|
||||
'#weight' => 10,
|
||||
];
|
||||
$page['#sorted'] = TRUE;
|
||||
$cacheable_metadata->addCacheContexts(['user.node_grants:view']);
|
||||
|
||||
// Display the reading history if that module is enabled.
|
||||
if ($this->moduleHandler()->moduleExists('history')) {
|
||||
// Reading history is tracked for authenticated users only.
|
||||
if ($this->currentUser()->isAuthenticated()) {
|
||||
$page['#attached']['library'][] = 'tracker/history';
|
||||
}
|
||||
$cacheable_metadata->addCacheContexts(['user.roles:authenticated']);
|
||||
}
|
||||
$cacheable_metadata->applyTo($page);
|
||||
return $page;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Controller;
|
||||
|
||||
@trigger_error(__NAMESPACE__ . '\TrackerPage is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use \Drupal\tracker\Controller\TrackerController instead. See https://www.drupal.org/node/3030645', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Controller for tracker.page route.
|
||||
*/
|
||||
class TrackerPage extends TrackerController {
|
||||
|
||||
/**
|
||||
* Content callback for the tracker.page route.
|
||||
*/
|
||||
public function getContent() {
|
||||
return $this->buildContent();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Controller;
|
||||
|
||||
@trigger_error(__NAMESPACE__ . '\TrackerUserRecent is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use \Drupal\tracker\Controller\TrackerController instead. See https://www.drupal.org/node/3030645', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Controller for tracker.users_recent_content route.
|
||||
*/
|
||||
class TrackerUserRecent extends TrackerController {
|
||||
|
||||
/**
|
||||
* Content callback for the tracker.users_recent_content route.
|
||||
*/
|
||||
public function getContent(UserInterface $user) {
|
||||
return $this->buildContent($user);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Controller;
|
||||
|
||||
@trigger_error(__NAMESPACE__ . '\TrackerUserTab is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use \Drupal\tracker\Controller\TrackerController instead. See https://www.drupal.org/node/3030645', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Controller for tracker.user_tab route.
|
||||
*/
|
||||
class TrackerUserTab extends TrackerController {
|
||||
|
||||
/**
|
||||
* Content callback for the tracker.user_tab route.
|
||||
*/
|
||||
public function getContent(UserInterface $user) {
|
||||
return $this->buildContent($user);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Plugin\Menu;
|
||||
|
||||
use Drupal\Core\Menu\LocalTaskDefault;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
|
||||
/**
|
||||
* Provides route parameters needed to link to the current user tracker tab.
|
||||
*/
|
||||
class UserTrackerTab extends LocalTaskDefault {
|
||||
|
||||
/**
|
||||
* Current user object.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Gets the current active user.
|
||||
*
|
||||
* @todo: https://www.drupal.org/node/2105123 put this method in
|
||||
* \Drupal\Core\Plugin\PluginBase instead.
|
||||
*
|
||||
* @return \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected function currentUser() {
|
||||
if (!$this->currentUser) {
|
||||
$this->currentUser = \Drupal::currentUser();
|
||||
}
|
||||
return $this->currentUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRouteParameters(RouteMatchInterface $route_match) {
|
||||
return ['user' => $this->currentUser()->Id()];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 7 tracker node source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_tracker_node",
|
||||
* source_module = "tracker"
|
||||
* )
|
||||
*/
|
||||
class TrackerNode extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('tracker_node', 'tn')->fields('tn');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'nid' => $this->t('The {node}.nid this record tracks.'),
|
||||
'published' => $this->t('Boolean indicating whether the node is published.'),
|
||||
'changed' => $this->t('The Unix timestamp when the node was most recently saved or commented on.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['nid']['type'] = 'integer';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 7 tracker user source from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_tracker_user",
|
||||
* source_module = "tracker"
|
||||
* )
|
||||
*/
|
||||
class TrackerUser extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('tracker_user', 'tu')->fields('tu');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'nid' => $this->t('The {user}.nid this record tracks.'),
|
||||
'uid' => $this->t('The {users}.uid of the node author or commenter.'),
|
||||
'published' => $this->t('Boolean indicating whether the node is published.'),
|
||||
'changed' => $this->t('The Unix timestamp when the user was most recently saved or commented on.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['nid']['type'] = 'integer';
|
||||
$ids['uid']['type'] = 'integer';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Plugin\views\argument;
|
||||
|
||||
use Drupal\comment\Plugin\views\argument\UserUid as CommentUserUid;
|
||||
|
||||
/**
|
||||
* UID argument to check for nodes that user posted or commented on.
|
||||
*
|
||||
* @ingroup views_argument_handlers
|
||||
*
|
||||
* @ViewsArgument("tracker_user_uid")
|
||||
*/
|
||||
class UserUid extends CommentUserUid {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query($group_by = FALSE) {
|
||||
// Because this handler thinks it's an argument for a field on the {node}
|
||||
// table, we need to make sure {tracker_user} is JOINed and use its alias
|
||||
// for the WHERE clause.
|
||||
$tracker_user_alias = $this->query->ensureTable('tracker_user');
|
||||
$this->query->addWhere(0, "$tracker_user_alias.uid", $this->argument);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Plugin\views\filter;
|
||||
|
||||
use Drupal\user\Plugin\views\filter\Name;
|
||||
|
||||
/**
|
||||
* UID filter to check for nodes that a user posted or commented on.
|
||||
*
|
||||
* @ingroup views_filter_handlers
|
||||
*
|
||||
* @ViewsFilter("tracker_user_uid")
|
||||
*/
|
||||
class UserUid extends Name {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
// Because this handler thinks it's an argument for a field on the {node}
|
||||
// table, we need to make sure {tracker_user} is JOINed and use its alias
|
||||
// for the WHERE clause.
|
||||
$tracker_user_alias = $this->query->ensureTable('tracker_user');
|
||||
// Cast scalars to array so we can consistently use an IN condition.
|
||||
$this->query->addWhere(0, "$tracker_user_alias.uid", (array) $this->value, 'IN');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\tracker\Tests\Views;
|
||||
|
||||
@trigger_error(__NAMESPACE__ . '\TrackerTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\tracker\Functional\Views\TrackerTestBase', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\comment\Entity\Comment;
|
||||
|
||||
/**
|
||||
* Base class for all tracker tests.
|
||||
*
|
||||
* @deprecated in drupal:8.?.? and is removed from drupal:9.0.0.
|
||||
* Use \Drupal\Tests\tracker\Functional\Views\TrackerTestBase instead.
|
||||
*/
|
||||
abstract class TrackerTestBase extends ViewTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['comment', 'tracker', 'tracker_test_views'];
|
||||
|
||||
/**
|
||||
* The node used for testing.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
/**
|
||||
* The comment used for testing.
|
||||
*
|
||||
* @var \Drupal\comment\CommentInterface
|
||||
*/
|
||||
protected $comment;
|
||||
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['tracker_test_views']);
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
// Add a comment field.
|
||||
$this->addDefaultCommentField('node', 'page');
|
||||
|
||||
$permissions = ['access comments', 'create page content', 'post comments', 'skip comment approval'];
|
||||
$account = $this->drupalCreateUser($permissions);
|
||||
|
||||
$this->drupalLogin($account);
|
||||
|
||||
$this->node = $this->drupalCreateNode([
|
||||
'title' => $this->randomMachineName(8),
|
||||
'uid' => $account->id(),
|
||||
'status' => 1,
|
||||
]);
|
||||
|
||||
$this->comment = Comment::create([
|
||||
'entity_id' => $this->node->id(),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'comment',
|
||||
'subject' => $this->randomMachineName(),
|
||||
'comment_body[' . LanguageInterface::LANGCODE_NOT_SPECIFIED . '][0][value]' => $this->randomMachineName(20),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user