Initial Drupal 11 with DDEV setup
This commit is contained in:
		@ -0,0 +1,57 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\history\Controller;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
use Symfony\Component\HttpFoundation\JsonResponse;
 | 
			
		||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 | 
			
		||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 | 
			
		||||
use Drupal\Core\Controller\ControllerBase;
 | 
			
		||||
use Drupal\node\NodeInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns responses for History module routes.
 | 
			
		||||
 */
 | 
			
		||||
class HistoryController extends ControllerBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns a set of nodes' last read timestamps.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Symfony\Component\HttpFoundation\Request $request
 | 
			
		||||
   *   The request of the page.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Symfony\Component\HttpFoundation\JsonResponse
 | 
			
		||||
   *   The JSON response.
 | 
			
		||||
   */
 | 
			
		||||
  public function getNodeReadTimestamps(Request $request) {
 | 
			
		||||
    if ($this->currentUser()->isAnonymous()) {
 | 
			
		||||
      throw new AccessDeniedHttpException();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!$request->request->has('node_ids')) {
 | 
			
		||||
      throw new NotFoundHttpException();
 | 
			
		||||
    }
 | 
			
		||||
    $nids = $request->request->all('node_ids');
 | 
			
		||||
    return new JsonResponse(history_read_multiple($nids));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Marks a node as read by the current user right now.
 | 
			
		||||
   *
 | 
			
		||||
   * @param \Symfony\Component\HttpFoundation\Request $request
 | 
			
		||||
   *   The request of the page.
 | 
			
		||||
   * @param \Drupal\node\NodeInterface $node
 | 
			
		||||
   *   The node whose "last read" timestamp should be updated.
 | 
			
		||||
   */
 | 
			
		||||
  public function readNode(Request $request, NodeInterface $node) {
 | 
			
		||||
    if ($this->currentUser()->isAnonymous()) {
 | 
			
		||||
      throw new AccessDeniedHttpException();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update the history table, stating that this user viewed this node.
 | 
			
		||||
    history_write($node->id());
 | 
			
		||||
 | 
			
		||||
    return new JsonResponse((int) history_read($node->id()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								web/core/modules/history/src/HistoryRenderCallback.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								web/core/modules/history/src/HistoryRenderCallback.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\history;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Render\Element\RenderCallbackInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Render callback object.
 | 
			
		||||
 */
 | 
			
		||||
class HistoryRenderCallback implements RenderCallbackInterface {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Render API callback: Attaches the last read timestamp for a node.
 | 
			
		||||
   *
 | 
			
		||||
   * This function is assigned as a #lazy_builder callback.
 | 
			
		||||
   *
 | 
			
		||||
   * @param int $node_id
 | 
			
		||||
   *   The node ID for which to attach the last read timestamp.
 | 
			
		||||
   *
 | 
			
		||||
   * @return array
 | 
			
		||||
   *   A renderable array containing the last read timestamp.
 | 
			
		||||
   */
 | 
			
		||||
  public static function lazyBuilder($node_id) {
 | 
			
		||||
    $element = [];
 | 
			
		||||
    $element['#attached']['drupalSettings']['history']['lastReadTimestamps'][$node_id] = (int) history_read($node_id);
 | 
			
		||||
    return $element;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								web/core/modules/history/src/Hook/HistoryHooks.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								web/core/modules/history/src/Hook/HistoryHooks.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,96 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\history\Hook;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
 | 
			
		||||
use Drupal\user\UserInterface;
 | 
			
		||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 | 
			
		||||
use Drupal\Core\Entity\EntityInterface;
 | 
			
		||||
use Drupal\Core\Url;
 | 
			
		||||
use Drupal\Core\Routing\RouteMatchInterface;
 | 
			
		||||
use Drupal\Core\Hook\Attribute\Hook;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Hook implementations for history.
 | 
			
		||||
 */
 | 
			
		||||
class HistoryHooks {
 | 
			
		||||
 | 
			
		||||
  use StringTranslationTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_help().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('help')]
 | 
			
		||||
  public function help($route_name, RouteMatchInterface $route_match): ?string {
 | 
			
		||||
    switch ($route_name) {
 | 
			
		||||
      case 'help.page.history':
 | 
			
		||||
        $output = '<h2>' . $this->t('About') . '</h2>';
 | 
			
		||||
        $output .= '<p>' . $this->t('The History module keeps track of which content a user has read. It marks content as <em>new</em> or <em>updated</em> depending on the last time the user viewed it. History records that are older than one month are removed during cron, which means that content older than one month is always considered <em>read</em>. The History module does not have a user interface but it provides a filter to <a href=":views-help">Views</a> to show new or updated content. For more information, see the <a href=":url">online documentation for the History module</a>.', [
 | 
			
		||||
          ':views-help' => \Drupal::moduleHandler()->moduleExists('views') ? Url::fromRoute('help.page', [
 | 
			
		||||
            'name' => 'views',
 | 
			
		||||
          ])->toString() : '#',
 | 
			
		||||
          ':url' => 'https://www.drupal.org/documentation/modules/history',
 | 
			
		||||
        ]) . '</p>';
 | 
			
		||||
        return $output;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_cron().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('cron')]
 | 
			
		||||
  public function cron(): void {
 | 
			
		||||
    \Drupal::database()->delete('history')->condition('timestamp', HISTORY_READ_LIMIT, '<')->execute();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_ENTITY_TYPE_view_alter() for node entities.
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('node_view_alter')]
 | 
			
		||||
  public function nodeViewAlter(array &$build, EntityInterface $node, EntityViewDisplayInterface $display): void {
 | 
			
		||||
    if ($node->isNew() || isset($node->in_preview)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    // Update the history table, stating that this user viewed this node.
 | 
			
		||||
    if ($display->getOriginalMode() === 'full') {
 | 
			
		||||
      $build['#cache']['contexts'][] = 'user.roles:authenticated';
 | 
			
		||||
      if (\Drupal::currentUser()->isAuthenticated()) {
 | 
			
		||||
        // When the window's "load" event is triggered, mark the node as read.
 | 
			
		||||
        // This still allows for Drupal behaviors (which are triggered on the
 | 
			
		||||
        // "DOMContentReady" event) to add "new" and "updated" indicators.
 | 
			
		||||
        $build['#attached']['library'][] = 'history/mark-as-read';
 | 
			
		||||
        $build['#attached']['drupalSettings']['history']['nodesToMarkAsRead'][$node->id()] = TRUE;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_ENTITY_TYPE_delete() for node entities.
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('node_delete')]
 | 
			
		||||
  public function nodeDelete(EntityInterface $node): void {
 | 
			
		||||
    \Drupal::database()->delete('history')->condition('nid', $node->id())->execute();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_user_cancel().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('user_cancel')]
 | 
			
		||||
  public function userCancel($edit, UserInterface $account, $method): void {
 | 
			
		||||
    switch ($method) {
 | 
			
		||||
      case 'user_cancel_reassign':
 | 
			
		||||
        \Drupal::database()->delete('history')->condition('uid', $account->id())->execute();
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_ENTITY_TYPE_delete() for user entities.
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('user_delete')]
 | 
			
		||||
  public function userDelete($account): void {
 | 
			
		||||
    \Drupal::database()->delete('history')->condition('uid', $account->id())->execute();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								web/core/modules/history/src/Hook/HistoryViewsHooks.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								web/core/modules/history/src/Hook/HistoryViewsHooks.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\history\Hook;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Hook\Attribute\Hook;
 | 
			
		||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Hook implementations for history.
 | 
			
		||||
 */
 | 
			
		||||
class HistoryViewsHooks {
 | 
			
		||||
 | 
			
		||||
  use StringTranslationTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_views_data().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('views_data')]
 | 
			
		||||
  public function viewsData(): array {
 | 
			
		||||
    // History table
 | 
			
		||||
    // We're actually defining a specific instance of the table, so let's
 | 
			
		||||
    // alias it so that we can later add the real table for other purposes if we
 | 
			
		||||
    // need it.
 | 
			
		||||
    $data['history']['table']['group'] = $this->t('Content');
 | 
			
		||||
    // Explain how this table joins to others.
 | 
			
		||||
    $data['history']['table']['join'] = [
 | 
			
		||||
          // Directly links to node table.
 | 
			
		||||
      'node_field_data' => [
 | 
			
		||||
        'table' => 'history',
 | 
			
		||||
        'left_field' => 'nid',
 | 
			
		||||
        'field' => 'nid',
 | 
			
		||||
        'extra' => [
 | 
			
		||||
                  [
 | 
			
		||||
                    'field' => 'uid',
 | 
			
		||||
                    'value' => '***CURRENT_USER***',
 | 
			
		||||
                    'numeric' => TRUE,
 | 
			
		||||
                  ],
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    $data['history']['timestamp'] = [
 | 
			
		||||
      'title' => $this->t('Has new content'),
 | 
			
		||||
      'field' => [
 | 
			
		||||
        'id' => 'history_user_timestamp',
 | 
			
		||||
        'help' => $this->t('Show a marker if the content is new or updated.'),
 | 
			
		||||
      ],
 | 
			
		||||
      'filter' => [
 | 
			
		||||
        'help' => $this->t('Show only content that is new or updated.'),
 | 
			
		||||
        'id' => 'history_user_timestamp',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    return $data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,110 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\history\Plugin\views\field;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Form\FormStateInterface;
 | 
			
		||||
use Drupal\views\Attribute\ViewsField;
 | 
			
		||||
use Drupal\views\ResultRow;
 | 
			
		||||
use Drupal\views\ViewExecutable;
 | 
			
		||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
 | 
			
		||||
use Drupal\node\Plugin\views\field\Node;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Field handler to display the marker for new content.
 | 
			
		||||
 *
 | 
			
		||||
 * The handler is named history_user, because of compatibility reasons, the
 | 
			
		||||
 * table is history.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup views_field_handlers
 | 
			
		||||
 */
 | 
			
		||||
#[ViewsField("history_user_timestamp")]
 | 
			
		||||
class HistoryUserTimestamp extends Node {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function usesGroupBy() {
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function init(ViewExecutable $view, DisplayPluginBase $display, ?array &$options = NULL) {
 | 
			
		||||
    parent::init($view, $display, $options);
 | 
			
		||||
 | 
			
		||||
    if (\Drupal::currentUser()->isAuthenticated()) {
 | 
			
		||||
      $this->additional_fields['created'] = ['table' => 'node_field_data', 'field' => 'created'];
 | 
			
		||||
      $this->additional_fields['changed'] = ['table' => 'node_field_data', 'field' => 'changed'];
 | 
			
		||||
      if (\Drupal::moduleHandler()->moduleExists('comment') && !empty($this->options['comments'])) {
 | 
			
		||||
        $this->additional_fields['last_comment'] = ['table' => 'comment_entity_statistics', 'field' => 'last_comment_timestamp'];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function defineOptions() {
 | 
			
		||||
    $options = parent::defineOptions();
 | 
			
		||||
 | 
			
		||||
    $options['comments'] = ['default' => FALSE];
 | 
			
		||||
 | 
			
		||||
    return $options;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
 | 
			
		||||
    parent::buildOptionsForm($form, $form_state);
 | 
			
		||||
    if (\Drupal::moduleHandler()->moduleExists('comment')) {
 | 
			
		||||
      $form['comments'] = [
 | 
			
		||||
        '#type' => 'checkbox',
 | 
			
		||||
        '#title' => $this->t('Check for new comments as well'),
 | 
			
		||||
        '#default_value' => !empty($this->options['comments']),
 | 
			
		||||
      ];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function query() {
 | 
			
		||||
    // Only add ourselves to the query if logged in.
 | 
			
		||||
    if (\Drupal::currentUser()->isAnonymous()) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    parent::query();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function render(ResultRow $values) {
 | 
			
		||||
    // Let's default to 'read' state.
 | 
			
		||||
    $mark = MARK_READ;
 | 
			
		||||
    if (\Drupal::currentUser()->isAuthenticated()) {
 | 
			
		||||
      $last_read = $this->getValue($values);
 | 
			
		||||
      $changed = $this->getValue($values, 'changed');
 | 
			
		||||
 | 
			
		||||
      $last_comment = \Drupal::moduleHandler()->moduleExists('comment') && !empty($this->options['comments']) ? $this->getValue($values, 'last_comment') : 0;
 | 
			
		||||
 | 
			
		||||
      if (!$last_read && $changed > HISTORY_READ_LIMIT) {
 | 
			
		||||
        $mark = MARK_NEW;
 | 
			
		||||
      }
 | 
			
		||||
      elseif ($changed > $last_read && $changed > HISTORY_READ_LIMIT) {
 | 
			
		||||
        $mark = MARK_UPDATED;
 | 
			
		||||
      }
 | 
			
		||||
      elseif ($last_comment > $last_read && $last_comment > HISTORY_READ_LIMIT) {
 | 
			
		||||
        $mark = MARK_UPDATED;
 | 
			
		||||
      }
 | 
			
		||||
      $build = [
 | 
			
		||||
        '#theme' => 'mark',
 | 
			
		||||
        '#status' => $mark,
 | 
			
		||||
      ];
 | 
			
		||||
      return $this->renderLink(\Drupal::service('renderer')->render($build), $values);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,143 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\history\Plugin\views\filter;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Datetime\TimeInterface;
 | 
			
		||||
use Drupal\Core\Cache\UncacheableDependencyTrait;
 | 
			
		||||
use Drupal\Core\Form\FormStateInterface;
 | 
			
		||||
use Drupal\views\Attribute\ViewsFilter;
 | 
			
		||||
use Drupal\views\Plugin\views\filter\FilterPluginBase;
 | 
			
		||||
use Symfony\Component\DependencyInjection\ContainerInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Filter for new content.
 | 
			
		||||
 *
 | 
			
		||||
 * The handler is named history_user, because of compatibility reasons, the
 | 
			
		||||
 * table is history.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup views_filter_handlers
 | 
			
		||||
 */
 | 
			
		||||
#[ViewsFilter("history_user_timestamp")]
 | 
			
		||||
class HistoryUserTimestamp extends FilterPluginBase {
 | 
			
		||||
 | 
			
		||||
  use UncacheableDependencyTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  // phpcs:ignore Drupal.NamingConventions.ValidVariableName.LowerCamelName, Drupal.Commenting.VariableComment.Missing
 | 
			
		||||
  public $no_operator = TRUE;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs a HistoryUserTimestamp 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\Component\Datetime\TimeInterface $time
 | 
			
		||||
   *   The time service.
 | 
			
		||||
   */
 | 
			
		||||
  public function __construct(array $configuration, $plugin_id, $plugin_definition, protected TimeInterface $time) {
 | 
			
		||||
    parent::__construct($configuration, $plugin_id, $plugin_definition);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
 | 
			
		||||
    return new static(
 | 
			
		||||
      $configuration,
 | 
			
		||||
      $plugin_id,
 | 
			
		||||
      $plugin_definition,
 | 
			
		||||
      $container->get('datetime.time'),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function usesGroupBy() {
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function buildExposeForm(&$form, FormStateInterface $form_state) {
 | 
			
		||||
    parent::buildExposeForm($form, $form_state);
 | 
			
		||||
    // @todo There are better ways of excluding required and multiple (object flags)
 | 
			
		||||
    unset($form['expose']['required']);
 | 
			
		||||
    unset($form['expose']['multiple']);
 | 
			
		||||
    unset($form['expose']['remember']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function valueForm(&$form, FormStateInterface $form_state) {
 | 
			
		||||
    // Only present a checkbox for the exposed filter itself. There's no way
 | 
			
		||||
    // to tell the difference between not checked and the default value, so
 | 
			
		||||
    // specifying the default value via the views UI is meaningless.
 | 
			
		||||
    if ($form_state->get('exposed')) {
 | 
			
		||||
      if (isset($this->options['expose']['label'])) {
 | 
			
		||||
        $label = $this->options['expose']['label'];
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        $label = $this->t('Has new content');
 | 
			
		||||
      }
 | 
			
		||||
      $form['value'] = [
 | 
			
		||||
        '#type' => 'checkbox',
 | 
			
		||||
        '#title' => $label,
 | 
			
		||||
        '#default_value' => $this->value,
 | 
			
		||||
      ];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function query() {
 | 
			
		||||
    // This can only work if we're authenticated in.
 | 
			
		||||
    if (!\Drupal::currentUser()->isAuthenticated()) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Don't filter if we're exposed and the checkbox isn't selected.
 | 
			
		||||
    if ((!empty($this->options['exposed'])) && empty($this->value)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Hey, Drupal kills old history, so nodes that haven't been updated
 | 
			
		||||
    // since HISTORY_READ_LIMIT are outta here!
 | 
			
		||||
    $limit = $this->time->getRequestTime() - HISTORY_READ_LIMIT;
 | 
			
		||||
 | 
			
		||||
    $this->ensureMyTable();
 | 
			
		||||
    $field = "$this->tableAlias.$this->realField";
 | 
			
		||||
    $node = $this->query->ensureTable('node_field_data', $this->relationship);
 | 
			
		||||
 | 
			
		||||
    $clause = '';
 | 
			
		||||
    $clause2 = '';
 | 
			
		||||
    if ($alias = $this->query->ensureTable('comment_entity_statistics', $this->relationship)) {
 | 
			
		||||
      $clause = "OR $alias.last_comment_timestamp > (***CURRENT_TIME*** - $limit)";
 | 
			
		||||
      $clause2 = "OR $field < $alias.last_comment_timestamp";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // NULL means a history record doesn't exist. That's clearly new content.
 | 
			
		||||
    // Unless it's very very old content. Everything in the query is already
 | 
			
		||||
    // type safe cause none of it is coming from outside here.
 | 
			
		||||
    $this->query->addWhereExpression($this->options['group'], "($field IS NULL AND ($node.changed > (***CURRENT_TIME*** - $limit) $clause)) OR $field < $node.changed $clause2");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function adminSummary() {
 | 
			
		||||
    if (!empty($this->options['exposed'])) {
 | 
			
		||||
      return $this->t('exposed');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user