diff --git a/core/modules/statistics/src/Plugin/Block/StatisticsPopularBlock.php b/core/modules/statistics/src/Plugin/Block/StatisticsPopularBlock.php index bb1dfd8..04c71fa 100644 --- a/core/modules/statistics/src/Plugin/Block/StatisticsPopularBlock.php +++ b/core/modules/statistics/src/Plugin/Block/StatisticsPopularBlock.php @@ -11,6 +11,9 @@ use Drupal\Core\Block\BlockBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\statistics\StatisticsStorageInterface; /** * Provides a 'Popular content' block. @@ -20,7 +23,14 @@ * admin_label = @Translation("Popular content") * ) */ -class StatisticsPopularBlock extends BlockBase { +class StatisticsPopularBlock extends BlockBase implements ContainerFactoryPluginInterface { + + /** + * The storage for statistics. + * + * @var \Drupal\statistics\StatisticsStorageInterface + */ + protected $statisticsStorage; /** * Number of day's top views to display. @@ -44,6 +54,35 @@ class StatisticsPopularBlock extends BlockBase { protected $last_list; /** + * Constructs an StatisticsPopularBlock object. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * @param \Drupal\statistics\StatisticsStorageInterface $statistics_storage + * The storage for statistics. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, StatisticsStorageInterface $statistics_storage) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->statisticsStorage = $statistics_storage; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('statistics.statistics_storage') + ); + } + + /** * {@inheritdoc} */ public function defaultConfiguration() { @@ -59,19 +98,18 @@ public function defaultConfiguration() { */ protected function blockAccess(AccountInterface $account) { - $storage = \Drupal::service('statistics.statistics_storage'); $access = AccessResult::allowedIfHasPermission($account, 'access content'); if ($account->hasPermission('access content')) { $daytop = $this->configuration['top_day_num']; - if (!$daytop || !($result = $storage->statisticsTitleList('daycount', $daytop)) || !($this->day_list = node_title_list($result, $this->t("Today's:")))) { + if (!$daytop || !($result = $this->statisticsStorage->statisticsTitleList('daycount', $daytop)) || !($this->day_list = node_title_list($result, $this->t("Today's:")))) { return AccessResult::forbidden()->inheritCacheability($access); } $alltimetop = $this->configuration['top_all_num']; - if (!$alltimetop || !($result = $storage->statisticsTitleList('totalcount', $alltimetop)) || !($this->all_time_list = node_title_list($result, $this->t('All time:')))) { + if (!$alltimetop || !($result = $this->statisticsStorage->statisticsTitleList('totalcount', $alltimetop)) || !($this->all_time_list = node_title_list($result, $this->t('All time:')))) { return AccessResult::forbidden()->inheritCacheability($access); } $lasttop = $this->configuration['top_last_num']; - if (!$lasttop || !($result = $storage->statisticsTitleList('timestamp', $lasttop)) || !($this->last_list = node_title_list($result, $this->t('Last viewed:')))) { + if (!$lasttop || !($result = $this->statisticsStorage->statisticsTitleList('timestamp', $lasttop)) || !($this->last_list = node_title_list($result, $this->t('Last viewed:')))) { return AccessResult::forbidden()->inheritCacheability($access); } return $access; diff --git a/core/modules/statistics/src/StatisticsDatabaseStorage.php b/core/modules/statistics/src/StatisticsDatabaseStorage.php index 20be456..b97b89f 100644 --- a/core/modules/statistics/src/StatisticsDatabaseStorage.php +++ b/core/modules/statistics/src/StatisticsDatabaseStorage.php @@ -3,6 +3,7 @@ namespace Drupal\statistics; use Drupal\Core\Database\Connection; +use Drupal\Core\State\StateInterface; class StatisticsDatabaseStorage implements StatisticsStorageInterface { @@ -14,13 +15,23 @@ class StatisticsDatabaseStorage implements StatisticsStorageInterface { protected $connection; /** + * The state service. + * + * @var \Drupal\Core\State\StateInterface + */ + protected $state; + + /** * Construct the statistics storage. * * @param \Drupal\Core\Database\Connection $connection * The database connection for the node view storage. + * @param \Drupal\Core\State\StateInterface $state + * The state service. */ - public function __construct(Connection $connection) { + public function __construct(Connection $connection, StateInterface $state) { $this->connection = $connection; + $this->state = $state; } /** @@ -29,26 +40,24 @@ public function __construct(Connection $connection) { public function recordHit($nid) { return (bool) $this->connection->merge('node_counter') ->key('nid', $nid) - ->fields(array( - 'daycount' => 1, - 'totalcount' => 1, - 'timestamp' => REQUEST_TIME, - )) + ->fields(array( + 'daycount' => 1, + 'totalcount' => 1, + 'timestamp' => REQUEST_TIME, + )) ->expression('daycount', 'daycount + 1') - ->expression('totalcount', 'totalcount + 1') - ->execute(); + ->expression('totalcount', 'totalcount + 1') + ->execute(); } /** * {@inheritdoc} */ public function fetchViews($nid) { - if ($nid > 0) { - // Retrieve an array with both totalcount and daycount. - return $this->connection->select('node_counter', 'nc') - ->fields('nc', array('totalcount', 'daycount', 'timestamp')) - ->condition('nid', $nid, '=')->execute()->fetchAssoc(); - } + // Retrieve an array with both totalcount, daycount and timestamp. + return $this->connection->select('node_counter', 'nc') + ->fields('nc', array('totalcount', 'daycount', 'timestamp')) + ->condition('nid', $nid, '=')->execute()->fetchAssoc(); } /** @@ -57,30 +66,54 @@ public function fetchViews($nid) { public function clean($nid) { return (bool) $this->connection->delete('node_counter') ->condition('nid', $nid) - ->execute(); + ->execute(); + } + + /** + * {@inheritdoc} + */ + public function needsReset() { + $statistics_timestamp = $this->state->get('statistics.day_timestamp') ?: 0; + return (REQUEST_TIME - $statistics_timestamp) >= 86400; } /** * {@inheritdoc} */ public function resetDayCount() { + $this->state->set('statistics.day_timestamp', REQUEST_TIME); return (bool) $this->connection->update('node_counter') ->fields(array('daycount' => 0)) - ->execute(); + ->execute(); } /** * {@inheritdoc} */ public function maxTotalCount() { - $q = $this->connection->select('node_counter', 'nc'); - $q->addExpression('MAX(totalcount)'); - return (int) $q->execute()->fetchField(); + $query = $this->connection->select('node_counter', 'nc'); + $query->addExpression('MAX(totalcount)'); + $max_total_count = (int)$query->execute()->fetchField(); + $this->state->set('statistics.node_counter_scale', 1.0 / max(1.0, $max_total_count)); + return $max_total_count; } /** - * {@inheritdoc} - */ + * Returns the most viewed content of all time, today, or the last-viewed node. + * + * @param string $dbfield + * The database field to use, one of: + * - 'totalcount': Integer that shows the top viewed content of all time. + * - 'daycount': Integer that shows the top viewed content for today. + * - 'timestamp': Integer that shows only the last viewed node. + * @param int $dbrows + * The number of rows to be returned. + * + * @return SelectQuery|FALSE + * A query result containing the node ID, title, user ID that owns the node, + * and the username for the selected node(s), or FALSE if the query could not + * be executed correctly. + */ public function statisticsTitleList($dbfield, $dbrows) { if (in_array($dbfield, array('totalcount', 'daycount', 'timestamp'))) { $query = $this->connection->select('node_field_data', 'n'); @@ -90,16 +123,16 @@ public function statisticsTitleList($dbfield, $dbrows) { return $query ->fields('n', array('nid', 'title')) - ->fields('u', array('uid', 'name')) - ->condition($dbfield, 0, '<>') - ->condition('n.status', 1) - // @todo This should be actually filtering on the desired node status - // field language and just fall back to the default language. - ->condition('n.default_langcode', 1) + ->fields('u', array('uid', 'name')) + ->condition($dbfield, 0, '<>') + ->condition('n.status', 1) + // @todo This should be actually filtering on the desired node status + // field language and just fall back to the default language. + ->condition('n.default_langcode', 1) ->condition('u.default_langcode', 1) - ->orderBy($dbfield, 'DESC') - ->range(0, $dbrows) - ->execute(); + ->orderBy($dbfield, 'DESC') + ->range(0, $dbrows) + ->execute(); } return FALSE; } diff --git a/core/modules/statistics/src/StatisticsStorageInterface.php b/core/modules/statistics/src/StatisticsStorageInterface.php index e6e9daf..e5243e9 100644 --- a/core/modules/statistics/src/StatisticsStorageInterface.php +++ b/core/modules/statistics/src/StatisticsStorageInterface.php @@ -15,74 +15,65 @@ interface StatisticsStorageInterface { /** - * Returns if node view is counted + * Count a node view. * * @param int $nid - * The id of the node to count + * The id of the node to count. * * @return bool - * TRUE if the node view has been counted + * TRUE if the node view has been counted. */ public function recordHit($nid); /** - * Returns the number of times a node has been viewed + * Returns the number of times a node has been viewed. * * @param int $nid - * The id of the node to fetch the views for + * The id of the node to fetch the views for. * - * @return array - * An associative array containing: - * - totalcount: Integer for the total number of times the node has been - * viewed. - * - daycount: Integer for the total number of times the node has been viewed - * "today". For the daycount to be reset, cron must be enabled. - * - timestamp: Integer for the timestamp of when the node was last viewed. + * @return array + * An associative array containing: + * - totalcount: Integer for the total number of times the node has been + * viewed. + * - daycount: Integer for the total number of times the node has been viewed + * "today". For the daycount to be reset, cron must be enabled. + * - timestamp: Integer for the timestamp of when the node was last viewed. */ public function fetchViews($nid); /** - * Returns if node view counts are delete + * Delete counts for a specific node. * * @param int $nid - * The id of the node which views to delete + * The id of the node which views to delete. * * @return bool - * TRUE if the node views have been deleted + * TRUE if the node views have been deleted. */ public function clean($nid); /** - * Returns if day count is reset + * Returns if reset is needed. * * @return bool - * TRUE if the day count is reset + * TRUE if reset is needed. */ - public function resetDayCount(); + public function needsReset(); /** - * Returns the highest 'totalcount' value + * Resets the day count for all nodes. * - * @return int - * The highest 'totalcount' value + * @return bool + * TRUE if the day count is reset. */ - public function maxTotalCount(); + public function resetDayCount(); /** - * Returns the most viewed content of all time, today, or the last-viewed node. + * Returns the highest 'totalcount' value. * - * @param string $dbfield - * The database field to use, one of: - * - 'totalcount': Integer that shows the top viewed content of all time. - * - 'daycount': Integer that shows the top viewed content for today. - * - 'timestamp': Integer that shows only the last viewed node. - * @param int $dbrows - * The number of rows to be returned. - * - * @return SelectQuery|FALSE - * A query result containing the node ID, title, user ID that owns the node, - * and the username for the selected node(s), or FALSE if the query could not - * be executed correctly. + * @return int + * The highest 'totalcount' value. */ - public function statisticsTitleList($dbfield, $dbrows); + public function maxTotalCount(); + } diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module index 675d6c8..5e969d4 100644 --- a/core/modules/statistics/statistics.module +++ b/core/modules/statistics/statistics.module @@ -69,37 +69,30 @@ function statistics_node_links_alter(array &$node_links, NodeInterface $entity, */ function statistics_cron() { $storage = \Drupal::service('statistics.statistics_storage'); - $statistics_timestamp = \Drupal::state()->get('statistics.day_timestamp') ?: 0; - - if ((REQUEST_TIME - $statistics_timestamp) >= 86400) { - // Reset day counts + if ($storage->needsReset()) { $storage->resetDayCount(); - \Drupal::state()->set('statistics.day_timestamp', REQUEST_TIME); } - // Calculate the maximum of node views, for node search ranking. $max_total_count = $storage->maxTotalCount(); - \Drupal::state()->set('statistics.node_counter_scale', 1.0 / max(1.0, $max_total_count)); } /** - * Retrieves a node's "view statistics". + * Returns the most viewed content of all time, today, or the last-viewed node. * - * @param int $nid - * The node ID. + * @deprecated in Drupal 8.0.x + */ +function statistics_title_list($dbfield, $dbrows) { + return \Drupal::service('statistics.statistics_storage')->statisticsTitleList($dbfield, $dbrows); +} + +/** + * Retrieves a node's "view statistics". * - * @return array - * An associative array containing: - * - totalcount: Integer for the total number of times the node has been - * viewed. - * - daycount: Integer for the total number of times the node has been viewed - * "today". For the daycount to be reset, cron must be enabled. - * - timestamp: Integer for the timestamp of when the node was last viewed. + * @deprecated in Drupal 8.0.x */ function statistics_get($nid) { if ($nid > 0) { - $storage = \Drupal::service('statistics.statistics_storage'); - return $storage->fetchViews($nid); + return \Drupal::service('statistics.statistics_storage')->fetchViews($nid); } } @@ -109,8 +102,7 @@ function statistics_get($nid) { function statistics_node_predelete(EntityInterface $node) { // Clean up statistics table when node is deleted. $nid = $node->id(); - $storage = \Drupal::service('statistics.statistics_storage'); - return $storage->clean($nid); + return \Drupal::service('statistics.statistics_storage')->clean($nid); } /** diff --git a/core/modules/statistics/statistics.services.yml b/core/modules/statistics/statistics.services.yml index 512ad5d..5053f2e 100644 --- a/core/modules/statistics/statistics.services.yml +++ b/core/modules/statistics/statistics.services.yml @@ -1,6 +1,6 @@ services: statistics.statistics_storage: class: Drupal\statistics\StatisticsDatabaseStorage - arguments: ['@database'] + arguments: ['@database', '@state'] tags: - { name: backend_overridable }