upgrades core to 8.4.2
This commit is contained in:
@@ -7,8 +7,8 @@ package: Core
|
||||
dependencies:
|
||||
- node
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-08-16
|
||||
version: '8.3.7'
|
||||
# Information added by Drupal.org packaging script on 2017-11-03
|
||||
version: '8.4.2'
|
||||
core: '8.x'
|
||||
project: 'drupal'
|
||||
datestamp: 1502903957
|
||||
datestamp: 1509719929
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* @file
|
||||
* JavaScript API for the History module, with client-side caching.
|
||||
*
|
||||
* May only be loaded for authenticated users, with the History module enabled.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, drupalSettings, storage) {
|
||||
const currentUserID = parseInt(drupalSettings.user.uid, 10);
|
||||
|
||||
// Any comment that is older than 30 days is automatically considered read,
|
||||
// so for these we don't need to perform a request at all!
|
||||
const thirtyDaysAgo = Math.round(new Date().getTime() / 1000) - 30 * 24 * 60 * 60;
|
||||
|
||||
// Use the data embedded in the page, if available.
|
||||
let embeddedLastReadTimestamps = false;
|
||||
if (drupalSettings.history && drupalSettings.history.lastReadTimestamps) {
|
||||
embeddedLastReadTimestamps = drupalSettings.history.lastReadTimestamps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
*/
|
||||
Drupal.history = {
|
||||
|
||||
/**
|
||||
* Fetch "last read" timestamps for the given nodes.
|
||||
*
|
||||
* @param {Array} nodeIDs
|
||||
* An array of node IDs.
|
||||
* @param {function} callback
|
||||
* A callback that is called after the requested timestamps were fetched.
|
||||
*/
|
||||
fetchTimestamps(nodeIDs, callback) {
|
||||
// Use the data embedded in the page, if available.
|
||||
if (embeddedLastReadTimestamps) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: Drupal.url('history/get_node_read_timestamps'),
|
||||
type: 'POST',
|
||||
data: { 'node_ids[]': nodeIDs },
|
||||
dataType: 'json',
|
||||
success(results) {
|
||||
for (const nodeID in results) {
|
||||
if (results.hasOwnProperty(nodeID)) {
|
||||
storage.setItem(`Drupal.history.${currentUserID}.${nodeID}`, results[nodeID]);
|
||||
}
|
||||
}
|
||||
callback();
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the last read timestamp for the given node.
|
||||
*
|
||||
* @param {number|string} nodeID
|
||||
* A node ID.
|
||||
*
|
||||
* @return {number}
|
||||
* A UNIX timestamp.
|
||||
*/
|
||||
getLastRead(nodeID) {
|
||||
// Use the data embedded in the page, if available.
|
||||
if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
|
||||
return parseInt(embeddedLastReadTimestamps[nodeID], 10);
|
||||
}
|
||||
return parseInt(storage.getItem(`Drupal.history.${currentUserID}.${nodeID}`) || 0, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Marks a node as read, store the last read timestamp client-side.
|
||||
*
|
||||
* @param {number|string} nodeID
|
||||
* A node ID.
|
||||
*/
|
||||
markAsRead(nodeID) {
|
||||
$.ajax({
|
||||
url: Drupal.url(`history/${nodeID}/read`),
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
success(timestamp) {
|
||||
// If the data is embedded in the page, don't store on the client
|
||||
// side.
|
||||
if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
|
||||
return;
|
||||
}
|
||||
|
||||
storage.setItem(`Drupal.history.${currentUserID}.${nodeID}`, timestamp);
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines whether a server check is necessary.
|
||||
*
|
||||
* Any content that is >30 days old never gets a "new" or "updated"
|
||||
* indicator. Any content that was published before the oldest known reading
|
||||
* also never gets a "new" or "updated" indicator, because it must've been
|
||||
* read already.
|
||||
*
|
||||
* @param {number|string} nodeID
|
||||
* A node ID.
|
||||
* @param {number} contentTimestamp
|
||||
* The time at which some content (e.g. a comment) was published.
|
||||
*
|
||||
* @return {bool}
|
||||
* Whether a server check is necessary for the given node and its
|
||||
* timestamp.
|
||||
*/
|
||||
needsServerCheck(nodeID, contentTimestamp) {
|
||||
// First check if the content is older than 30 days, then we can bail
|
||||
// early.
|
||||
if (contentTimestamp < thirtyDaysAgo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use the data embedded in the page, if available.
|
||||
if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
|
||||
return contentTimestamp > parseInt(embeddedLastReadTimestamps[nodeID], 10);
|
||||
}
|
||||
|
||||
const minLastReadTimestamp = parseInt(storage.getItem(`Drupal.history.${currentUserID}.${nodeID}`) || 0, 10);
|
||||
return contentTimestamp > minLastReadTimestamp;
|
||||
},
|
||||
};
|
||||
}(jQuery, Drupal, drupalSettings, window.localStorage));
|
||||
@@ -1,41 +1,22 @@
|
||||
/**
|
||||
* @file
|
||||
* JavaScript API for the History module, with client-side caching.
|
||||
*
|
||||
* May only be loaded for authenticated users, with the History module enabled.
|
||||
*/
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function ($, Drupal, drupalSettings, storage) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var currentUserID = parseInt(drupalSettings.user.uid, 10);
|
||||
|
||||
// Any comment that is older than 30 days is automatically considered read,
|
||||
// so for these we don't need to perform a request at all!
|
||||
var thirtyDaysAgo = Math.round(new Date().getTime() / 1000) - 30 * 24 * 60 * 60;
|
||||
|
||||
// Use the data embedded in the page, if available.
|
||||
var embeddedLastReadTimestamps = false;
|
||||
if (drupalSettings.history && drupalSettings.history.lastReadTimestamps) {
|
||||
embeddedLastReadTimestamps = drupalSettings.history.lastReadTimestamps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
*/
|
||||
Drupal.history = {
|
||||
|
||||
/**
|
||||
* Fetch "last read" timestamps for the given nodes.
|
||||
*
|
||||
* @param {Array} nodeIDs
|
||||
* An array of node IDs.
|
||||
* @param {function} callback
|
||||
* A callback that is called after the requested timestamps were fetched.
|
||||
*/
|
||||
fetchTimestamps: function (nodeIDs, callback) {
|
||||
// Use the data embedded in the page, if available.
|
||||
fetchTimestamps: function fetchTimestamps(nodeIDs, callback) {
|
||||
if (embeddedLastReadTimestamps) {
|
||||
callback();
|
||||
return;
|
||||
@@ -44,9 +25,9 @@
|
||||
$.ajax({
|
||||
url: Drupal.url('history/get_node_read_timestamps'),
|
||||
type: 'POST',
|
||||
data: {'node_ids[]': nodeIDs},
|
||||
data: { 'node_ids[]': nodeIDs },
|
||||
dataType: 'json',
|
||||
success: function (results) {
|
||||
success: function success(results) {
|
||||
for (var nodeID in results) {
|
||||
if (results.hasOwnProperty(nodeID)) {
|
||||
storage.setItem('Drupal.history.' + currentUserID + '.' + nodeID, results[nodeID]);
|
||||
@@ -56,38 +37,18 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the last read timestamp for the given node.
|
||||
*
|
||||
* @param {number|string} nodeID
|
||||
* A node ID.
|
||||
*
|
||||
* @return {number}
|
||||
* A UNIX timestamp.
|
||||
*/
|
||||
getLastRead: function (nodeID) {
|
||||
// Use the data embedded in the page, if available.
|
||||
getLastRead: function getLastRead(nodeID) {
|
||||
if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
|
||||
return parseInt(embeddedLastReadTimestamps[nodeID], 10);
|
||||
}
|
||||
return parseInt(storage.getItem('Drupal.history.' + currentUserID + '.' + nodeID) || 0, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Marks a node as read, store the last read timestamp client-side.
|
||||
*
|
||||
* @param {number|string} nodeID
|
||||
* A node ID.
|
||||
*/
|
||||
markAsRead: function (nodeID) {
|
||||
markAsRead: function markAsRead(nodeID) {
|
||||
$.ajax({
|
||||
url: Drupal.url('history/' + nodeID + '/read'),
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
success: function (timestamp) {
|
||||
// If the data is embedded in the page, don't store on the client
|
||||
// side.
|
||||
success: function success(timestamp) {
|
||||
if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
|
||||
return;
|
||||
}
|
||||
@@ -96,32 +57,11 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines whether a server check is necessary.
|
||||
*
|
||||
* Any content that is >30 days old never gets a "new" or "updated"
|
||||
* indicator. Any content that was published before the oldest known reading
|
||||
* also never gets a "new" or "updated" indicator, because it must've been
|
||||
* read already.
|
||||
*
|
||||
* @param {number|string} nodeID
|
||||
* A node ID.
|
||||
* @param {number} contentTimestamp
|
||||
* The time at which some content (e.g. a comment) was published.
|
||||
*
|
||||
* @return {bool}
|
||||
* Whether a server check is necessary for the given node and its
|
||||
* timestamp.
|
||||
*/
|
||||
needsServerCheck: function (nodeID, contentTimestamp) {
|
||||
// First check if the content is older than 30 days, then we can bail
|
||||
// early.
|
||||
needsServerCheck: function needsServerCheck(nodeID, contentTimestamp) {
|
||||
if (contentTimestamp < thirtyDaysAgo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use the data embedded in the page, if available.
|
||||
if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
|
||||
return contentTimestamp > parseInt(embeddedLastReadTimestamps[nodeID], 10);
|
||||
}
|
||||
@@ -130,5 +70,4 @@
|
||||
return contentTimestamp > minLastReadTimestamp;
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery, Drupal, drupalSettings, window.localStorage);
|
||||
})(jQuery, Drupal, drupalSettings, window.localStorage);
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @file
|
||||
* Marks the nodes listed in drupalSettings.history.nodesToMarkAsRead as read.
|
||||
*
|
||||
* Uses the History module JavaScript API.
|
||||
*
|
||||
* @see Drupal.history
|
||||
*/
|
||||
|
||||
(function (window, Drupal, drupalSettings) {
|
||||
// When the window's "load" event is triggered, mark all enumerated nodes as
|
||||
// read. This still allows for Drupal behaviors (which are triggered on the
|
||||
// "DOMContentReady" event) to add "new" and "updated" indicators.
|
||||
window.addEventListener('load', () => {
|
||||
if (drupalSettings.history && drupalSettings.history.nodesToMarkAsRead) {
|
||||
Object.keys(drupalSettings.history.nodesToMarkAsRead).forEach(Drupal.history.markAsRead);
|
||||
}
|
||||
});
|
||||
}(window, Drupal, drupalSettings));
|
||||
@@ -1,23 +1,14 @@
|
||||
/**
|
||||
* @file
|
||||
* Marks the nodes listed in drupalSettings.history.nodesToMarkAsRead as read.
|
||||
*
|
||||
* Uses the History module JavaScript API.
|
||||
*
|
||||
* @see Drupal.history
|
||||
*/
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function (window, Drupal, drupalSettings) {
|
||||
|
||||
'use strict';
|
||||
|
||||
// When the window's "load" event is triggered, mark all enumerated nodes as
|
||||
// read. This still allows for Drupal behaviors (which are triggered on the
|
||||
// "DOMContentReady" event) to add "new" and "updated" indicators.
|
||||
window.addEventListener('load', function () {
|
||||
if (drupalSettings.history && drupalSettings.history.nodesToMarkAsRead) {
|
||||
Object.keys(drupalSettings.history.nodesToMarkAsRead).forEach(Drupal.history.markAsRead);
|
||||
}
|
||||
});
|
||||
|
||||
})(window, Drupal, drupalSettings);
|
||||
})(window, Drupal, drupalSettings);
|
||||
@@ -51,7 +51,7 @@ class HistoryController extends ControllerBase {
|
||||
// Update the history table, stating that this user viewed this node.
|
||||
history_write($node->id());
|
||||
|
||||
return new JsonResponse((int)history_read($node->id()));
|
||||
return new JsonResponse((int) history_read($node->id()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class HistoryUserTimestamp extends Node {
|
||||
'#theme' => 'mark',
|
||||
'#status' => $mark,
|
||||
];
|
||||
return $this->renderLink(drupal_render($build), $values);
|
||||
return $this->renderLink(\Drupal::service('renderer')->render($build), $values);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace Drupal\Tests\history\Functional;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use GuzzleHttp\Cookie\CookieJar;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\history\Kernel\Views;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the history timestamp handlers.
|
||||
*
|
||||
* @group history
|
||||
* @see \Drupal\history\Plugin\views\field\HistoryUserTimestamp
|
||||
* @see \Drupal\history\Plugin\views\filter\HistoryUserTimestamp
|
||||
*/
|
||||
class HistoryTimestampTest extends ViewsKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['history', 'node'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_history'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE) {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('history', ['history']);
|
||||
// Use classy theme because its marker is wrapped in a span so it can be
|
||||
// easily targeted with xpath.
|
||||
\Drupal::service('theme_handler')->install(['classy']);
|
||||
\Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme('classy'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the handlers.
|
||||
*/
|
||||
public function testHandlers() {
|
||||
$nodes = [];
|
||||
$node = Node::create([
|
||||
'title' => 'n1',
|
||||
'type' => 'default',
|
||||
]);
|
||||
$node->save();
|
||||
$nodes[] = $node;
|
||||
$node = Node::create([
|
||||
'title' => 'n2',
|
||||
'type' => 'default',
|
||||
]);
|
||||
$node->save();
|
||||
$nodes[] = $node;
|
||||
|
||||
$account = User::create(['name' => 'admin']);
|
||||
$account->save();
|
||||
\Drupal::currentUser()->setAccount($account);
|
||||
|
||||
db_insert('history')
|
||||
->fields([
|
||||
'uid' => $account->id(),
|
||||
'nid' => $nodes[0]->id(),
|
||||
'timestamp' => REQUEST_TIME - 100,
|
||||
])->execute();
|
||||
|
||||
db_insert('history')
|
||||
->fields([
|
||||
'uid' => $account->id(),
|
||||
'nid' => $nodes[1]->id(),
|
||||
'timestamp' => REQUEST_TIME + 100,
|
||||
])->execute();
|
||||
|
||||
|
||||
$column_map = [
|
||||
'nid' => 'nid',
|
||||
];
|
||||
|
||||
// Test the history field.
|
||||
$view = Views::getView('test_history');
|
||||
$view->setDisplay('page_1');
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 2);
|
||||
$output = $view->preview();
|
||||
$this->setRawContent(\Drupal::service('renderer')->renderRoot($output));
|
||||
$result = $this->xpath('//span[@class=:class]', [':class' => 'marker']);
|
||||
$this->assertEqual(count($result), 1, 'Just one node is marked as new');
|
||||
|
||||
// Test the history filter.
|
||||
$view = Views::getView('test_history');
|
||||
$view->setDisplay('page_2');
|
||||
$this->executeView($view);
|
||||
$this->assertEqual(count($view->result), 1);
|
||||
$this->assertIdenticalResultset($view, [['nid' => $nodes[0]->id()]], $column_map);
|
||||
|
||||
// Install Comment module and make sure that content types without comment
|
||||
// field will not break the view.
|
||||
// See \Drupal\history\Plugin\views\filter\HistoryUserTimestamp::query()
|
||||
\Drupal::service('module_installer')->install(['comment']);
|
||||
$view = Views::getView('test_history');
|
||||
$view->setDisplay('page_2');
|
||||
$this->executeView($view);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user