Skip to content
Snippets Groups Projects
Verified Commit 529c7932 authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3349394 by plopesc, fjgarlin, hestenet, penyaskito, friera: Provide...

Issue #3349394 by plopesc, fjgarlin, hestenet, penyaskito, friera: Provide announcement feed as a block
parent d088a7b0
No related branches found
No related tags found
No related merge requests found
......@@ -15,3 +15,7 @@ services:
class: Drupal\announcements_feed\LazyBuilders
arguments: [ '@plugin.manager.element_info']
Drupal\announcements_feed\LazyBuilders: '@announcements_feed.lazy_builders'
announcements_feed.renderer:
class: Drupal\announcements_feed\AnnounceRenderer
arguments: ['@announcements_feed.fetcher', '%announcements_feed.feed_link%']
Drupal\announcements_feed\AnnounceRenderer: '@announcements_feed.renderer'
<?php
declare(strict_types=1);
namespace Drupal\announcements_feed;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* Service to render announcements from the external feed.
*
* @internal
*/
final class AnnounceRenderer {
use StringTranslationTrait;
/**
* Constructs an AnnouncementRenderer object.
*
* @param \Drupal\announcements_feed\AnnounceFetcher $announceFetcher
* The AnnounceFetcher service.
* @param string $feedLink
* The feed url path.
*/
public function __construct(
protected AnnounceFetcher $announceFetcher,
protected string $feedLink
) {
}
/**
* Generates the announcements feed render array.
*
* @return array
* Render array containing the announcements feed.
*/
public function render(): array {
try {
$announcements = $this->announceFetcher->fetch();
}
catch (\Exception $e) {
return [
'#theme' => 'status_messages',
'#message_list' => [
'error' => [
$this->t('An error occurred while parsing the announcements feed, check the logs for more information.'),
],
],
'#status_headings' => [
'error' => $this->t('Error Message'),
],
];
}
$build = [];
foreach ($announcements as $announcement) {
$key = $announcement->featured ? '#featured' : '#standard';
$build[$key][] = $announcement;
}
$build += [
'#theme' => 'announcements_feed',
'#count' => count($announcements),
'#feed_link' => $this->feedLink,
'#cache' => [
'contexts' => [
'url.query_args:_wrapper_format',
],
'tags' => [
'announcements_feed:feed',
],
],
'#attached' => [
'library' => [
'announcements_feed/drupal.announcements_feed.dialog',
],
],
];
return $build;
}
}
......@@ -4,9 +4,9 @@
namespace Drupal\announcements_feed\Controller;
use Drupal\announcements_feed\AnnounceRenderer;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\announcements_feed\AnnounceFetcher;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
......@@ -20,14 +20,11 @@ class AnnounceController extends ControllerBase implements ContainerInjectionInt
/**
* Constructs an AnnounceController object.
*
* @param \Drupal\announcements_feed\AnnounceFetcher $announceFetcher
* The AnnounceFetcher service.
* @param string $feedLink
* The feed url path.
* @param \Drupal\announcements_feed\AnnounceRenderer $announceRenderer
* The AnnounceRenderer service.
*/
public function __construct(
protected AnnounceFetcher $announceFetcher,
protected string $feedLink
protected AnnounceRenderer $announceRenderer,
) {
}
......@@ -36,8 +33,7 @@ public function __construct(
*/
public static function create(ContainerInterface $container): AnnounceController {
return new static(
$container->get('announcements_feed.fetcher'),
$container->getParameter('announcements_feed.feed_link')
$container->get('announcements_feed.renderer'),
);
}
......@@ -51,47 +47,7 @@ public static function create(ContainerInterface $container): AnnounceController
* A build array with announcements.
*/
public function getAnnouncements(Request $request): array {
try {
$announcements = $this->announceFetcher->fetch();
}
catch (\Exception $e) {
return [
'#theme' => 'status_messages',
'#message_list' => [
'error' => [
$this->t('An error occurred while parsing the announcements feed, check the logs for more information.'),
],
],
'#status_headings' => [
'error' => $this->t('Error Message'),
],
];
}
$build = [];
foreach ($announcements as $announcement) {
$key = $announcement->featured ? '#featured' : '#standard';
$build[$key][] = $announcement;
}
$build += [
'#theme' => 'announcements_feed',
'#count' => count($announcements),
'#feed_link' => $this->feedLink,
'#cache' => [
'contexts' => [
'url.query_args:_wrapper_format',
],
'tags' => [
'announcements_feed:feed',
],
],
'#attached' => [
'library' => [
'announcements_feed/drupal.announcements_feed.dialog',
],
],
];
$build = $this->announceRenderer->render();
if ($request->query->get('_wrapper_format') != 'drupal_dialog.off_canvas') {
$build['#theme'] = 'announcements_feed_admin';
$build['#attached'] = [];
......
<?php
declare(strict_types=1);
namespace Drupal\announcements_feed\Plugin\Block;
use Drupal\announcements_feed\AnnounceRenderer;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides an 'Announcements Feed' block.
*
* @Block(
* id = "announce_block",
* admin_label = @Translation("Announcements Feed"),
* )
*
* @internal
*/
class AnnounceBlock extends BlockBase implements ContainerFactoryPluginInterface {
/**
* Constructs a new AnnouncementsFeedBlock instance.
*
* @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\announcements_feed\AnnounceRenderer $announceRenderer
* The AnnounceRenderer service.
* @param \Drupal\Core\Session\AccountInterface $currentUser
* The current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, protected AnnounceRenderer $announceRenderer, protected AccountInterface $currentUser) {
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('announcements_feed.renderer'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function access(AccountInterface $account, $return_as_object = FALSE) {
return AccessResult::allowedIfHasPermission($this->currentUser, 'access announcements');
}
/**
* {@inheritdoc}
*/
public function build() {
return $this->announceRenderer->render();
}
}
<?php
declare(strict_types=1);
namespace Drupal\Tests\announcements_feed\FunctionalJavascript;
use Drupal\announce_feed_test\AnnounceTestHttpClientMiddleware;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Test the announcement block test visibility.
*
* @group announcements_feed
*/
class AnnounceBlockTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'announcements_feed',
'block',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* The announce block instance.
*
* @var \Drupal\block\Entity\Block
*/
protected $announceBlock;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
AnnounceTestHttpClientMiddleware::setAnnounceTestEndpoint('/announce-feed-json/community-feeds');
$this->announceBlock = $this->placeBlock('announce_block', [
'label' => 'Announcements Feed',
]);
}
/**
* Testing announce feed block visibility.
*/
public function testAnnounceWithoutPermission() {
// User with "access announcements" permission.
$account = $this->drupalCreateUser([
'access announcements',
]);
$this->drupalLogin($account);
$this->drupalGet('<front>');
$assert_session = $this->assertSession();
// Block should be visible for the user.
$assert_session->pageTextContains('Announcements Feed');
// Block is not accessible without permission.
$this->drupalLogout();
$assert_session->pageTextNotContains('Announcements Feed');
}
}
<?php
declare(strict_types=1);
namespace Drupal\Tests\announcements_feed\Kernel;
use GuzzleHttp\Psr7\Response;
/**
* @coversDefaultClass \Drupal\announcements_feed\AnnounceRenderer
*
* @group announcements_feed
*/
class AnnounceRendererTest extends AnnounceTestBase {
/**
* Tests rendered valid when something goes wrong.
*/
public function testRendererException() {
$this->setTestFeedResponses([
new Response(403),
]);
$render = $this->container->get('announcements_feed.renderer')->render();
$this->assertEquals('status_messages', $render['#theme']);
$this->assertEquals('An error occurred while parsing the announcements feed, check the logs for more information.', $render['#message_list']['error'][0]);
}
/**
* Tests rendered valid content.
*/
public function testRendererContent() {
$feed_item_1 = [
'id' => '1001',
'content_html' => 'Test teaser 1',
'url' => 'https://www.drupal.org/project/announce',
'_drupalorg' => [
'featured' => TRUE,
'version' => '^10||^11',
],
'date_modified' => "2021-09-02T15:09:42+00:00",
'date_published' => "2021-09-01T15:09:42+00:00",
];
$feed_item_2 = [
'id' => '1002',
'content_html' => 'Test teaser 1',
'url' => 'https://www.drupal.org/project/announce',
'_drupalorg' => [
'featured' => FALSE,
'version' => '^10||^11',
],
'date_modified' => "2021-09-02T15:09:42+00:00",
'date_published' => "2021-09-01T15:09:42+00:00",
];
$this->setFeedItems([$feed_item_1, $feed_item_2]);
$render = $this->container->get('announcements_feed.renderer')->render();
$this->assertEquals('announcements_feed', $render['#theme']);
$this->assertEquals(1, $render['#count']);
$this->assertEquals(1001, $render['#featured'][0]->id);
$render = $this->container->get('announcements_feed.renderer')->render();
$this->assertEquals('announcements_feed', $render['#theme']);
$this->assertEquals(1, $render['#count']);
$this->assertEquals(1002, $render['#standard'][0]->id);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment