Skip to content

Commit d5c57b0

Browse files
Pantheon Automationpwtyler
Pantheon Automation
authored andcommitted
Update to Drupal 7.100. For more information, see https://www.drupal.org/project/drupal/releases/7.100
1 parent d1eb2d8 commit d5c57b0

24 files changed

+1291
-4
lines changed

.gitlab-ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ stages:
139139
- composer require --dev drupal/coder:^8.2@stable micheh/phpcs-gitlab phpcompatibility/php-compatibility dealerdirect/phpcodesniffer-composer-installer
140140
- export TARGET_BRANCH=${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}${CI_COMMIT_BRANCH}
141141
script:
142-
- git fetch -vn --depth=$GIT_DEPTH "${CI_MERGE_REQUEST_PROJECT_URL:-origin}" "+refs/heads/$TARGET_BRANCH:refs/heads/$TARGET_BRANCH"
142+
- git fetch -vn --depth=$GIT_DEPTH origin "+refs/heads/$TARGET_BRANCH:refs/heads/$TARGET_BRANCH"
143143
- export MODIFIED=`git diff --name-only refs/heads/$TARGET_BRANCH|while read r;do echo "$CI_PROJECT_DIR/$r";done|tr "\n" " "`
144144
- echo -e "$MODIFIED" | tr " " "\n"
145145
- echo "If this list contains more files than what you changed, then you need to rebase your branch."

.gitlab-ci/pipeline.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ stages:
104104
- *prepare-dirs
105105
- *install-drupal
106106
- export TARGET_BRANCH=${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}${CI_COMMIT_BRANCH}
107-
- git fetch -vn --depth=50 "$CI_MERGE_REQUEST_PROJECT_URL" "+refs/heads/$TARGET_BRANCH:refs/heads/$TARGET_BRANCH"
107+
- git fetch -vn --depth=50 origin "+refs/heads/$TARGET_BRANCH:refs/heads/$TARGET_BRANCH"
108108
- |
109109
echo "ℹ️ Changes from ${TARGET_BRANCH}"
110110
git diff ${CI_MERGE_REQUEST_DIFF_BASE_SHA} --name-only

CHANGELOG.txt

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Drupal 7.100, 2024-03-06
2+
------------------------
3+
- Security improvements
4+
- Announcements module added
5+
16
Drupal 7.99, 2023-12-06
27
-----------------------
38
- Various security improvements

includes/bootstrap.inc

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
/**
99
* The current system version.
1010
*/
11-
define('VERSION', '7.99');
11+
define('VERSION', '7.100');
1212

1313
/**
1414
* Core API compatibility.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
/**
4+
* @file
5+
* Template file for the theming of announcements_feed admin page.
6+
*
7+
* Available variables:
8+
* - $count: Contains the total number of announcements.
9+
* - $featured: An array of featured announcements.
10+
* - $standard: An array of non-featured announcements.
11+
*
12+
* Each $announcement in $featured and $standard contain:
13+
* - $announcement['id']: Unique id of the announcement.
14+
* - $announcement['title']: Title of the announcement.
15+
* - $announcement['teaser']: Short description of the announcement.
16+
* - $announcement['link']: Learn more link of the announcement.
17+
* - $announcement['date_published']: Timestamp of the announcement.
18+
*
19+
* @see announcements_feed_theme()
20+
*
21+
* @ingroup themeable
22+
*/
23+
?>
24+
<?php if ($count): ?>
25+
<div class="announcements">
26+
<ul class="admin-list">
27+
<?php if ($featured): ?>
28+
<div class="featured-announcements-wrapper">
29+
<?php foreach ($featured as $key => $announcement): ?>
30+
<li class="leaf">
31+
<div class="announcement-title">
32+
<h4>
33+
<?php print $announcement['title']; ?>
34+
</h4>
35+
</div>
36+
<div class="announcement-teaser">
37+
<?php print strip_tags($announcement['teaser']); ?>
38+
</div>
39+
<div class="announcement-link">
40+
<?php if($announcement['link']): ?>
41+
<a target="_blank" href="<?php print $announcement['link']; ?>">
42+
<span>
43+
<?php print t('Learn More'); ?>
44+
</span>
45+
</a>
46+
<?php endif; ?>
47+
</div>
48+
</li>
49+
<?php endforeach; ?>
50+
</div>
51+
<?php endif; ?>
52+
<?php if ($standard): ?>
53+
<?php foreach ($standard as $key => $announcement): ?>
54+
<li class="leaf">
55+
<a target="_blank" href="<?php print $announcement['link']; ?>"><?php print $announcement['title']; ?></a>
56+
<div class="description">
57+
<?php print format_date(strtotime($announcement['date_published']), 'short'); ?>
58+
</div>
59+
</li>
60+
<?php endforeach; ?>
61+
<?php endif; ?>
62+
</ul>
63+
<?php if ($feed_link): ?>
64+
<div class="announcements--view-all">
65+
<a target="_blank" href="<?php print $feed_link; ?>"><?php print t('View all announcements'); ?></a>
66+
</div>
67+
<?php endif; ?>
68+
</div>
69+
<?php else: ?>
70+
<div class="no-announcements"><span><?php print t('No announcements available'); ?></span></div>
71+
<?php endif; ?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @file
3+
* Styles for the announcements feed.
4+
*/
5+
6+
.announcements {
7+
padding-bottom: 1rem;
8+
}
9+
.featured-announcements-wrapper .leaf {
10+
padding-top: 0;
11+
}
12+
.announcements .announcements--view-all {
13+
padding-left: 30px;
14+
border-top: 1px solid #ccc;
15+
padding-top: 10px;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
<?php
2+
3+
/**
4+
* @file
5+
* Announcements feed helper functions.
6+
*/
7+
8+
/**
9+
* Returns the list of announcements.
10+
*
11+
* @return array
12+
* A build array with announcements.
13+
*/
14+
function announcements_feed_get_announcements() {
15+
drupal_set_title(t('Community announcements'));
16+
drupal_add_css(drupal_get_path('module', 'announcements_feed')
17+
. '/announcements_feed.css', array(
18+
'group' => CSS_DEFAULT,
19+
'every_page' => TRUE,
20+
));
21+
try {
22+
$announcements = announcements_feed_get_all_announcements();
23+
}
24+
catch (Exception $e) {
25+
drupal_set_message(t('An error occurred while parsing the announcements feed, check the logs for more information.'), 'error');
26+
return array();
27+
}
28+
$build = array();
29+
foreach ($announcements as $announcement) {
30+
$key = $announcement['featured'] ? '#featured' : '#standard';
31+
$build[$key][] = $announcement;
32+
}
33+
$build = array_merge($build, array(
34+
'#theme' => 'announcements_feed',
35+
'#count' => count($announcements),
36+
'#feed_link' => variable_get('announcements_feed_link', ANNOUNCEMENTS_FEED_DEFAULT_LINK),
37+
));
38+
return $build;
39+
}
40+
41+
/**
42+
* Generate an array of announcements with keys.
43+
*
44+
* @return array
45+
* An array of announcements.
46+
*/
47+
function announcements_feed_get_all_announcements() {
48+
$announcements = announcements_feed_fetch();
49+
$announcements_feed = array();
50+
foreach ($announcements as $announcement) {
51+
$announcements_feed[] = array(
52+
'id' => $announcement['id'],
53+
'title' => $announcement['title'],
54+
'link' => $announcement['url'],
55+
'date_modified' => $announcement['date_modified'],
56+
'date_published' => $announcement['date_published'],
57+
'teaser' => $announcement['content_html'],
58+
'version' => $announcement['_drupalorg']['version'],
59+
'featured' => (bool) $announcement['_drupalorg']['featured'],
60+
);
61+
}
62+
63+
return $announcements_feed;
64+
}
65+
66+
/**
67+
* Fetches the feed either from a local cache or fresh remotely.
68+
*
69+
* The feed follows the "JSON Feed" format:
70+
* - https://www.jsonfeed.org/version/1.1/
71+
*
72+
* The structure of an announcement item in the feed is:
73+
* - id: Id.
74+
* - title: Title of the announcement.
75+
* - content_html: Announcement teaser.
76+
* - url: URL
77+
* - date_modified: Last updated timestamp.
78+
* - date_published: Created timestamp.
79+
* - _drupalorg.featured: 1 if featured, 0 if not featured.
80+
* - _drupalorg.version: Target version of Drupal, as a Composer version.
81+
*
82+
* @param bool $force
83+
* (optional) Whether to always fetch new items or not. Defaults to FALSE.
84+
*
85+
* @return array
86+
* An array of announcements from the feed relevant to the Drupal version.
87+
* The array is empty if there were no matching announcements. If an error
88+
* occurred while fetching/decoding the feed, it is thrown as an exception.
89+
*
90+
* @throws Exception
91+
*/
92+
function announcements_feed_fetch($force = FALSE) {
93+
$announcements = cache_get('announcements_feed');
94+
if ($force || empty($announcements)) {
95+
$announcements_feed_json_url = variable_get('announcements_feed_json_url', ANNOUNCEMENTS_FEED_DEFAULT_JSON_URL);
96+
$response = drupal_http_request($announcements_feed_json_url);
97+
if ($response->code == 200) {
98+
$feeds = json_decode($response->data, TRUE);
99+
if (!isset($feeds['items'])) {
100+
watchdog('announcements_feed', 'The feed format is not valid.', NULL, WATCHDOG_ERROR);
101+
throw new Exception('Announcements feed JSON format is invalid');
102+
}
103+
$announcements = array();
104+
if ($feeds['items']) {
105+
$announcements = $feeds['items'];
106+
}
107+
$announcements = array_filter($announcements, 'announcements_feed_filter_announcements');
108+
cache_set('announcements_feed', $announcements, 'cache', REQUEST_TIME + variable_get('announcements_feed_max_age', ANNOUNCEMENTS_FEED_DEFAULT_MAX_AGE));
109+
}
110+
else {
111+
watchdog(
112+
'announcements_feed',
113+
'The feed failed to fetch with an error code: @code, error message: @message.',
114+
array('@code' => $response->code, '@message' => $response->error),
115+
WATCHDOG_ERROR
116+
);
117+
throw new Exception($response->error, $response->code);
118+
}
119+
}
120+
else {
121+
$announcements = $announcements->data;
122+
}
123+
// The drupal.org endpoint is sorted by created date in descending order.
124+
// We will limit the announcements based on the configuration limit.
125+
$announcements_feed_limit = variable_get('announcements_feed_limit', ANNOUNCEMENTS_FEED_DEFAULT_LIMIT);
126+
$announcements = array_slice($announcements, 0, $announcements_feed_limit);
127+
// For the remaining announcements, put all the featured announcements
128+
// before the rest.
129+
uasort($announcements, 'announcements_feed_sort_featured');
130+
131+
return $announcements;
132+
}
133+
134+
/**
135+
* Sort the elements of announcements_feed by values in comparison function.
136+
*/
137+
function announcements_feed_sort_featured($a, $b) {
138+
$a_value = (int) $a['_drupalorg']['featured'];
139+
$b_value = (int) $b['_drupalorg']['featured'];
140+
if ($a_value == $b_value) {
141+
return 0;
142+
}
143+
144+
return ($a_value < $b_value) ? -1 : 1;
145+
}
146+
147+
/**
148+
* Filter the announcements relevant to the Drupal version used with valid URL controlled by drupal.org.
149+
*
150+
* @param array $announcement
151+
* Announcement feed array item to check.
152+
*
153+
* @return bool
154+
* Return TRUE if $announcement is relevant and the URL is valid.
155+
*/
156+
function announcements_feed_filter_announcements($announcement) {
157+
$announcement_url = '';
158+
$announcement_version = '';
159+
if (!empty($announcement['url'])) {
160+
$announcement_url = $announcement['url'];
161+
}
162+
if (!empty($announcement['_drupalorg']['version'])) {
163+
$announcement_version = $announcement['_drupalorg']['version'];
164+
}
165+
166+
return announcements_feed_validate_url($announcement_url) && announcements_feed_is_relevant_item($announcement_version);
167+
}
168+
169+
/**
170+
* Check whether the version given is relevant to the Drupal version used.
171+
*
172+
* @param string $version
173+
* Version to check.
174+
*
175+
* @return bool
176+
* Return TRUE if the version matches Drupal version.
177+
*/
178+
function announcements_feed_is_relevant_item($version) {
179+
if ($version == '*') {
180+
return TRUE;
181+
}
182+
// Split the version if received in || formats.
183+
$version_patterns = '/\|\|/';
184+
$all_versions = preg_split($version_patterns, $version);
185+
// The operation is optional and defaults to equals.
186+
$p_op = '(?P<operation>!=|\^|==|=|<|<=|>|>=|<>)?';
187+
$operations = '=';
188+
// Extracts major version from version string like 7, 8, 9.
189+
$p_major = '(?P<major>\d+)';
190+
// Extracts minor version from version string.
191+
$p_minor = '(?P<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
192+
foreach ($all_versions as $version) {
193+
if (preg_match("/^\s*$p_op\s*$p_major(\.$p_minor)?/", $version, $matches)) {
194+
$feed_version = $matches['major'];
195+
if (!empty($matches['minor'])) {
196+
$feed_version = $matches['major'] . '.' . $matches['minor'];
197+
}
198+
if (!empty($matches['operation'])) {
199+
$operations = $matches['operation'];
200+
if ($operations == '^') {
201+
$operations = '>=';
202+
}
203+
}
204+
if (isset($operations) && version_compare(VERSION, $feed_version, $operations)) {
205+
return TRUE;
206+
}
207+
}
208+
}
209+
210+
return FALSE;
211+
}
212+
213+
/**
214+
* Check whether a link is controlled by drupal.org.
215+
*
216+
* @param string $url
217+
* URL to check.
218+
*
219+
* @return bool
220+
* Return TRUE if the URL is controlled by drupal.org.
221+
*/
222+
function announcements_feed_validate_url($url) {
223+
if (empty($url)) {
224+
return FALSE;
225+
}
226+
$host = parse_url($url, PHP_URL_HOST);
227+
228+
// First character can only be a letter or a digit.
229+
// @see https://www.rfc-editor.org/rfc/rfc1123#page-13
230+
return $host && preg_match('/^([a-zA-Z0-9][a-zA-Z0-9\-_]*\.)?drupal\.org$/', $host);
231+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name = Announcements
2+
description = Displays announcements from the Drupal community.
3+
package = Core
4+
version = VERSION
5+
core = 7.x
6+
files[] = tests/announce_feed_test.test
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/**
4+
* @file
5+
* Install, update, and uninstall functions for the announcements_feed module.
6+
*/
7+
8+
/**
9+
* Implements hook_uninstall().
10+
*/
11+
function announcements_feed_uninstall() {
12+
// Delete the announcements_feed module variables.
13+
variable_del('announcements_feed_limit');
14+
variable_del('announcements_feed_cron_interval');
15+
variable_del('announcements_feed_max_age');
16+
variable_del('announcements_feed_json_url');
17+
variable_del('announcements_feed_link');
18+
variable_del('announcements_feed_last_fetch');
19+
}

0 commit comments

Comments
 (0)