o365-2.0.3/modules/o365_outlook_calendar/src/Plugin/Block/CalendarBlock.php
modules/o365_outlook_calendar/src/Plugin/Block/CalendarBlock.php
<?php
namespace Drupal\o365_outlook_calendar\Plugin\Block;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\o365\Block\O365UncachedBlockBase;
use Drupal\o365\GraphService;
use Drupal\o365\HelperService;
use Drupal\o365\PersonaRenderService;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a 'Upcoming Appointments' block.
*
* @Block(
* id = "o365_outlook_calendar",
* admin_label = @Translation("Upcoming Appointments"),
* category = @Translation("Microsoft 365")
* )
*/
final class CalendarBlock extends O365UncachedBlockBase implements ContainerFactoryPluginInterface {
use StringTranslationTrait;
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
GraphService $graphService,
protected HelperService $helperService,
protected DateFormatter $dateFormatter,
protected PersonaRenderService $personaRenderService,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $graphService);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('o365.graph'),
$container->get('o365.helpers'),
$container->get('date.formatter'),
$container->get('o365.profile_render')
);
}
/**
* {@inheritdoc}
*/
public function blockForm($form, FormStateInterface $form_state): array {
$form = parent::blockForm($form, $form_state);
$config = $this->getConfiguration();
$form['amount'] = [
'#type' => 'number',
'#title' => $this->t('Amount of events to show.'),
'#default_value' => $config['amount'] ?? 5,
'#min' => 1,
'#max' => 999,
];
$form['show_calendar_block'] = [
'#type' => 'checkbox',
'#title' => $this->t('Show the calendar block when there is no data'),
'#default_value' => $config['show_calendar_block'] ?? 0,
];
$form['calendar_block_text'] = [
'#type' => 'textarea',
'#title' => $this->t('Mail block text'),
'#description' => $this->t('Enter the text you would like to show'),
'#placeholder' => $this->t('Enter the text you would like to show'),
'#default_value' => $config['calendar_block_text'] ?? $this->t('No calendar items found.'),
'#states' => [
'visible' => [
':input[name="settings[show_calendar_block]"]' => [
'checked' => TRUE,
],
],
],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function blockSubmit($form, FormStateInterface $form_state): void {
$values = $form_state->getValues();
$this->configuration['amount'] = $values['amount'];
$this->configuration['show_calendar_block'] = $values['show_calendar_block'];
$this->configuration['calendar_block_text'] = $values['calendar_block_text'];
}
/**
* {@inheritdoc}
*
* @throws \Drupal\Core\TempStore\TempStoreException
* @throws \League\OAuth2\Client\Provider\Exception\IdentityProviderException
* @throws \Exception
*/
public function build(): array {
$config = $this->getConfiguration();
$amount = $config['amount'] ?? 5;
$build = [];
$fromDateTimestamp = date('U');
$toDateTimestamp = strtotime('now + 30 days');
$selectFromDate = $this->helperService->createIsoDate((int) $fromDateTimestamp);
$selectEndDate = $this->helperService->createIsoDate((int) $toDateTimestamp);
$eventData = $this->graphService->getGraphData('/me/calendarview?$top=' . $amount . '&$orderby=start/dateTime&$select=subject,start,end,attendees,isOnlineMeeting,onlineMeeting,webLink&startdatetime=' . $selectFromDate . '&enddatetime=' . $selectEndDate);
$items = [];
if (isset($eventData['value']) && !empty($eventData['value'])) {
$webLinkText = $this->t('This link opens in a new window');
$urlOptions = [
'attributes' => [
'target' => '_blank',
'title' => $webLinkText,
],
];
foreach ($eventData['value'] as $event) {
$eventUrl = Url::fromUri($event['webLink'], $urlOptions);
$onlineMeeting = FALSE;
if ($event['isOnlineMeeting']) {
$onlineMeeting = $event['onlineMeeting']['joinUrl'];
}
$webLink = Link::fromTextAndUrl($webLinkText, $eventUrl);
$fromTs = $this->helperService->getTsFromDate($event['start']['dateTime'], $event['start']['timeZone']);
$endTs = $this->helperService->getTsFromDate($event['end']['dateTime'], $event['end']['timeZone']);
// Get the attendees for this event.
$attendees = [];
$this->getAttendees($event['attendees'], $attendees);
$items[] = [
'#theme' => 'o365_calendar',
'#subject' => $event['subject'],
'#fromTime' => $this->dateFormatter->format((int) $fromTs, 'o365_outlook_calendar_time'),
'#endTime' => $this->dateFormatter->format((int) $endTs, 'o365_outlook_calendar_time'),
'#fromDate' => $this->dateFormatter->format((int) $fromTs, 'o365_outlook_calendar_day'),
'#endDate' => $this->dateFormatter->format((int) $endTs, 'o365_outlook_calendar_day'),
'#fromTs' => $fromTs,
'#endTs' => $endTs,
'#attendees' => $attendees['attendees'] ?? FALSE,
'#remainingAttendees' => $attendees['remaining'] ?? FALSE,
'#webLink' => $webLink,
'#onlineMeeting' => $onlineMeeting,
'#onlineMeeting_class' => 'button--primary button',
];
}
}
$build['content'] = [
'#theme' => 'o365_calendar_list',
'#no_items_text' => NULL,
'#list' => [
'#theme' => 'item_list',
'#items' => NULL,
'#attributes' => [
'class' => ['o365-outlook-calendar-items'],
],
'#wrapper_attributes' => [
'class' => [
'card__body',
],
],
],
'#cache' => [
'contexts' => [
'user',
],
],
'#attached' => [
'library' => [
'o365/persona',
'o365_outlook_calendar/o365_outlook_calendar',
],
],
];
if (empty($items) && (isset($config['show_calendar_block']) && !$config['show_calendar_block'])) {
return [];
}
$build['content']['#no_items_text'] = ($config['calendar_block_text']) ?? '';
$build['content']['#list']['#items'] = $items;
return $build;
}
/**
* Get the attendees for an event.
*
* @param array $attendees
* The attendees list.
* @param array|bool $result
* The result.
*/
private function getAttendees(array $attendees, &$result): void {
if (!empty($attendees)) {
$result['attendees'] = [];
$result['remaining'] = FALSE;
// Determine remaining, we only show 3.
$count = count($attendees);
if ($count > 3) {
$result['remaining'] = $count - 3;
}
// Generate the initials and color per user.
for ($count = 0; $count < 3; $count++) {
if (isset($attendees[$count])) {
$attendee = $attendees[$count];
$value = [
'bg' => $this->personaRenderService->getRandomPersonaColor(),
];
$initials = explode(' ', $attendee['emailAddress']['name']);
if (count($initials) > 1) {
$first = reset($initials);
$last = end($initials);
$value['initials'] = strtoupper($first[0] . $last[0]);
}
else {
$value['initials'] = strtoupper($initials[0][0]);
}
$result['attendees'][] = $value;
}
}
}
else {
$result = FALSE;
}
}
}
