Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Drupal 7.100. For more information, see https://www.drupal.org/project/drupal/releases/7.100 #200

Merged
merged 1 commit into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ stages:
- composer require --dev drupal/coder:^8.2@stable micheh/phpcs-gitlab phpcompatibility/php-compatibility dealerdirect/phpcodesniffer-composer-installer
- export TARGET_BRANCH=${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}${CI_COMMIT_BRANCH}
script:
- git fetch -vn --depth=$GIT_DEPTH "${CI_MERGE_REQUEST_PROJECT_URL:-origin}" "+refs/heads/$TARGET_BRANCH:refs/heads/$TARGET_BRANCH"
- git fetch -vn --depth=$GIT_DEPTH origin "+refs/heads/$TARGET_BRANCH:refs/heads/$TARGET_BRANCH"
- export MODIFIED=`git diff --name-only refs/heads/$TARGET_BRANCH|while read r;do echo "$CI_PROJECT_DIR/$r";done|tr "\n" " "`
- echo -e "$MODIFIED" | tr " " "\n"
- echo "If this list contains more files than what you changed, then you need to rebase your branch."
Expand Down
2 changes: 1 addition & 1 deletion .gitlab-ci/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ stages:
- *prepare-dirs
- *install-drupal
- export TARGET_BRANCH=${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}${CI_COMMIT_BRANCH}
- git fetch -vn --depth=50 "$CI_MERGE_REQUEST_PROJECT_URL" "+refs/heads/$TARGET_BRANCH:refs/heads/$TARGET_BRANCH"
- git fetch -vn --depth=50 origin "+refs/heads/$TARGET_BRANCH:refs/heads/$TARGET_BRANCH"
- |
echo "ℹ️ Changes from ${TARGET_BRANCH}"
git diff ${CI_MERGE_REQUEST_DIFF_BASE_SHA} --name-only
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
Drupal 7.100, 2024-03-06
------------------------
- Security improvements
- Announcements module added

Drupal 7.99, 2023-12-06
-----------------------
- Various security improvements
Expand Down
2 changes: 1 addition & 1 deletion includes/bootstrap.inc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* The current system version.
*/
define('VERSION', '7.99');
define('VERSION', '7.100');

/**
* Core API compatibility.
Expand Down
71 changes: 71 additions & 0 deletions modules/announcements_feed/announcements-feed.tpl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

/**
* @file
* Template file for the theming of announcements_feed admin page.
*
* Available variables:
* - $count: Contains the total number of announcements.
* - $featured: An array of featured announcements.
* - $standard: An array of non-featured announcements.
*
* Each $announcement in $featured and $standard contain:
* - $announcement['id']: Unique id of the announcement.
* - $announcement['title']: Title of the announcement.
* - $announcement['teaser']: Short description of the announcement.
* - $announcement['link']: Learn more link of the announcement.
* - $announcement['date_published']: Timestamp of the announcement.
*
* @see announcements_feed_theme()
*
* @ingroup themeable
*/
?>
<?php if ($count): ?>
<div class="announcements">
<ul class="admin-list">
<?php if ($featured): ?>
<div class="featured-announcements-wrapper">
<?php foreach ($featured as $key => $announcement): ?>
<li class="leaf">
<div class="announcement-title">
<h4>
<?php print $announcement['title']; ?>
</h4>
</div>
<div class="announcement-teaser">
<?php print strip_tags($announcement['teaser']); ?>
</div>
<div class="announcement-link">
<?php if($announcement['link']): ?>
<a target="_blank" href="<?php print $announcement['link']; ?>">
<span>
<?php print t('Learn More'); ?>
</span>
</a>
<?php endif; ?>
</div>
</li>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($standard): ?>
<?php foreach ($standard as $key => $announcement): ?>
<li class="leaf">
<a target="_blank" href="<?php print $announcement['link']; ?>"><?php print $announcement['title']; ?></a>
<div class="description">
<?php print format_date(strtotime($announcement['date_published']), 'short'); ?>
</div>
</li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
<?php if ($feed_link): ?>
<div class="announcements--view-all">
<a target="_blank" href="<?php print $feed_link; ?>"><?php print t('View all announcements'); ?></a>
</div>
<?php endif; ?>
</div>
<?php else: ?>
<div class="no-announcements"><span><?php print t('No announcements available'); ?></span></div>
<?php endif; ?>
16 changes: 16 additions & 0 deletions modules/announcements_feed/announcements_feed.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @file
* Styles for the announcements feed.
*/

.announcements {
padding-bottom: 1rem;
}
.featured-announcements-wrapper .leaf {
padding-top: 0;
}
.announcements .announcements--view-all {
padding-left: 30px;
border-top: 1px solid #ccc;
padding-top: 10px;
}
231 changes: 231 additions & 0 deletions modules/announcements_feed/announcements_feed.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
<?php

/**
* @file
* Announcements feed helper functions.
*/

/**
* Returns the list of announcements.
*
* @return array
* A build array with announcements.
*/
function announcements_feed_get_announcements() {
drupal_set_title(t('Community announcements'));
drupal_add_css(drupal_get_path('module', 'announcements_feed')
. '/announcements_feed.css', array(
'group' => CSS_DEFAULT,
'every_page' => TRUE,
));
try {
$announcements = announcements_feed_get_all_announcements();
}
catch (Exception $e) {
drupal_set_message(t('An error occurred while parsing the announcements feed, check the logs for more information.'), 'error');
return array();
}
$build = array();
foreach ($announcements as $announcement) {
$key = $announcement['featured'] ? '#featured' : '#standard';
$build[$key][] = $announcement;
}
$build = array_merge($build, array(
'#theme' => 'announcements_feed',
'#count' => count($announcements),
'#feed_link' => variable_get('announcements_feed_link', ANNOUNCEMENTS_FEED_DEFAULT_LINK),
));
return $build;
}

/**
* Generate an array of announcements with keys.
*
* @return array
* An array of announcements.
*/
function announcements_feed_get_all_announcements() {
$announcements = announcements_feed_fetch();
$announcements_feed = array();
foreach ($announcements as $announcement) {
$announcements_feed[] = array(
'id' => $announcement['id'],
'title' => $announcement['title'],
'link' => $announcement['url'],
'date_modified' => $announcement['date_modified'],
'date_published' => $announcement['date_published'],
'teaser' => $announcement['content_html'],
'version' => $announcement['_drupalorg']['version'],
'featured' => (bool) $announcement['_drupalorg']['featured'],
);
}

return $announcements_feed;
}

/**
* Fetches the feed either from a local cache or fresh remotely.
*
* The feed follows the "JSON Feed" format:
* - https://www.jsonfeed.org/version/1.1/
*
* The structure of an announcement item in the feed is:
* - id: Id.
* - title: Title of the announcement.
* - content_html: Announcement teaser.
* - url: URL
* - date_modified: Last updated timestamp.
* - date_published: Created timestamp.
* - _drupalorg.featured: 1 if featured, 0 if not featured.
* - _drupalorg.version: Target version of Drupal, as a Composer version.
*
* @param bool $force
* (optional) Whether to always fetch new items or not. Defaults to FALSE.
*
* @return array
* An array of announcements from the feed relevant to the Drupal version.
* The array is empty if there were no matching announcements. If an error
* occurred while fetching/decoding the feed, it is thrown as an exception.
*
* @throws Exception
*/
function announcements_feed_fetch($force = FALSE) {
$announcements = cache_get('announcements_feed');
if ($force || empty($announcements)) {
$announcements_feed_json_url = variable_get('announcements_feed_json_url', ANNOUNCEMENTS_FEED_DEFAULT_JSON_URL);
$response = drupal_http_request($announcements_feed_json_url);
if ($response->code == 200) {
$feeds = json_decode($response->data, TRUE);
if (!isset($feeds['items'])) {
watchdog('announcements_feed', 'The feed format is not valid.', NULL, WATCHDOG_ERROR);
throw new Exception('Announcements feed JSON format is invalid');
}
$announcements = array();
if ($feeds['items']) {
$announcements = $feeds['items'];
}
$announcements = array_filter($announcements, 'announcements_feed_filter_announcements');
cache_set('announcements_feed', $announcements, 'cache', REQUEST_TIME + variable_get('announcements_feed_max_age', ANNOUNCEMENTS_FEED_DEFAULT_MAX_AGE));
}
else {
watchdog(
'announcements_feed',
'The feed failed to fetch with an error code: @code, error message: @message.',
array('@code' => $response->code, '@message' => $response->error),
WATCHDOG_ERROR
);
throw new Exception($response->error, $response->code);
}
}
else {
$announcements = $announcements->data;
}
// The drupal.org endpoint is sorted by created date in descending order.
// We will limit the announcements based on the configuration limit.
$announcements_feed_limit = variable_get('announcements_feed_limit', ANNOUNCEMENTS_FEED_DEFAULT_LIMIT);
$announcements = array_slice($announcements, 0, $announcements_feed_limit);
// For the remaining announcements, put all the featured announcements
// before the rest.
uasort($announcements, 'announcements_feed_sort_featured');

return $announcements;
}

/**
* Sort the elements of announcements_feed by values in comparison function.
*/
function announcements_feed_sort_featured($a, $b) {
$a_value = (int) $a['_drupalorg']['featured'];
$b_value = (int) $b['_drupalorg']['featured'];
if ($a_value == $b_value) {
return 0;
}

return ($a_value < $b_value) ? -1 : 1;
}

/**
* Filter the announcements relevant to the Drupal version used with valid URL controlled by drupal.org.
*
* @param array $announcement
* Announcement feed array item to check.
*
* @return bool
* Return TRUE if $announcement is relevant and the URL is valid.
*/
function announcements_feed_filter_announcements($announcement) {
$announcement_url = '';
$announcement_version = '';
if (!empty($announcement['url'])) {
$announcement_url = $announcement['url'];
}
if (!empty($announcement['_drupalorg']['version'])) {
$announcement_version = $announcement['_drupalorg']['version'];
}

return announcements_feed_validate_url($announcement_url) && announcements_feed_is_relevant_item($announcement_version);
}

/**
* Check whether the version given is relevant to the Drupal version used.
*
* @param string $version
* Version to check.
*
* @return bool
* Return TRUE if the version matches Drupal version.
*/
function announcements_feed_is_relevant_item($version) {
if ($version == '*') {
return TRUE;
}
// Split the version if received in || formats.
$version_patterns = '/\|\|/';
$all_versions = preg_split($version_patterns, $version);
// The operation is optional and defaults to equals.
$p_op = '(?P<operation>!=|\^|==|=|<|<=|>|>=|<>)?';
$operations = '=';
// Extracts major version from version string like 7, 8, 9.
$p_major = '(?P<major>\d+)';
// Extracts minor version from version string.
$p_minor = '(?P<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
foreach ($all_versions as $version) {
if (preg_match("/^\s*$p_op\s*$p_major(\.$p_minor)?/", $version, $matches)) {
$feed_version = $matches['major'];
if (!empty($matches['minor'])) {
$feed_version = $matches['major'] . '.' . $matches['minor'];
}
if (!empty($matches['operation'])) {
$operations = $matches['operation'];
if ($operations == '^') {
$operations = '>=';
}
}
if (isset($operations) && version_compare(VERSION, $feed_version, $operations)) {
return TRUE;
}
}
}

return FALSE;
}

/**
* Check whether a link is controlled by drupal.org.
*
* @param string $url
* URL to check.
*
* @return bool
* Return TRUE if the URL is controlled by drupal.org.
*/
function announcements_feed_validate_url($url) {
if (empty($url)) {
return FALSE;
}
$host = parse_url($url, PHP_URL_HOST);

// First character can only be a letter or a digit.
// @see https://www.rfc-editor.org/rfc/rfc1123#page-13
return $host && preg_match('/^([a-zA-Z0-9][a-zA-Z0-9\-_]*\.)?drupal\.org$/', $host);
}
6 changes: 6 additions & 0 deletions modules/announcements_feed/announcements_feed.info
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name = Announcements
description = Displays announcements from the Drupal community.
package = Core
version = VERSION
core = 7.x
files[] = tests/announce_feed_test.test
19 changes: 19 additions & 0 deletions modules/announcements_feed/announcements_feed.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

/**
* @file
* Install, update, and uninstall functions for the announcements_feed module.
*/

/**
* Implements hook_uninstall().
*/
function announcements_feed_uninstall() {
// Delete the announcements_feed module variables.
variable_del('announcements_feed_limit');
variable_del('announcements_feed_cron_interval');
variable_del('announcements_feed_max_age');
variable_del('announcements_feed_json_url');
variable_del('announcements_feed_link');
variable_del('announcements_feed_last_fetch');
}
Loading
Loading