class Instances in Smart Date 3.3.x
Same name and namespace in other branches
- 8.2 modules/smart_date_recur/src/Controller/Instances.php \Drupal\smart_date_recur\Controller\Instances
- 3.x modules/smart_date_recur/src/Controller/Instances.php \Drupal\smart_date_recur\Controller\Instances
- 3.0.x modules/smart_date_recur/src/Controller/Instances.php \Drupal\smart_date_recur\Controller\Instances
- 3.1.x modules/smart_date_recur/src/Controller/Instances.php \Drupal\smart_date_recur\Controller\Instances
- 3.2.x modules/smart_date_recur/src/Controller/Instances.php \Drupal\smart_date_recur\Controller\Instances
- 3.4.x modules/smart_date_recur/src/Controller/Instances.php \Drupal\smart_date_recur\Controller\Instances
Provides listings of instances (with overrides) for a specified rule.
Hierarchy
- class \Drupal\Core\Controller\ControllerBase implements ContainerInjectionInterface uses LoggerChannelTrait, MessengerTrait, RedirectDestinationTrait, StringTranslationTrait
- class \Drupal\smart_date_recur\Controller\Instances
Expanded class hierarchy of Instances
4 files declare their use of Instances
- FullCalendarController.php in src/
Controller/ FullCalendarController.php - SmartDateOverrideDeleteForm.php in modules/
smart_date_recur/ src/ Form/ SmartDateOverrideDeleteForm.php - SmartDateOverrideForm.php in modules/
smart_date_recur/ src/ Form/ SmartDateOverrideForm.php - SmartDateRemoveInstanceForm.php in modules/
smart_date_recur/ src/ Form/ SmartDateRemoveInstanceForm.php
File
- modules/
smart_date_recur/ src/ Controller/ Instances.php, line 21
Namespace
Drupal\smart_date_recur\ControllerView source
class Instances extends ControllerBase {
/**
* The rrule object whose instances are being listed.
*
* @var \Drupal\smart_date_recur\Entity\SmartDateRule
*/
protected $rrule;
/**
* The entity storage class.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $storage;
/**
* The entity type ID.
*
* @var string
*/
protected $entityTypeId;
/**
* Information about the entity type.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Indicating whether current controller instance uses Ajax.
*
* @var bool
*/
private $useAjax;
/**
* Provide a list of rule items with operations to change rule items.
*
* @return array
* A render array of list of instances, with actions/operations.
*/
public function listInstancesOutput() {
if (!($entity = $this->rrule
->getParentEntity())) {
return $this
->returnError();
}
$field_name = $this->rrule->field_name
->getString();
if ($this->rrule->limit
->isEmpty()) {
$month_limit = SmartDateRule::getMonthsLimit($this->rrule);
$before = strtotime('+' . (int) $month_limit . ' months');
}
else {
$before = NULL;
}
// Use generated instances so we have a full list, and override as we go.
$gen_instances = $this->rrule
->makeRuleInstances($before)
->toArray();
$instances = [];
foreach ($gen_instances as $gen_instance) {
$gen_index = $gen_instance
->getIndex();
$instances[$gen_index] = [
'value' => $gen_instance
->getStart()
->getTimestamp(),
'end_value' => $gen_instance
->getEnd()
->getTimestamp(),
];
}
if (empty($instances)) {
return $this
->returnError();
}
$overrides = $this->rrule
->getRuleOverrides();
// Build headers.
// Iterate through rows and check for existing overrides.
foreach ($instances as $index => &$instance) {
$row_class = '';
// Check for an override.
if (isset($overrides[$index])) {
// Check for rescheduled, overridden, or cancelled
// add an appropriate class for each, and actions.
$override = $overrides[$index];
if ($override->entity_id
->getString()) {
// Overridden, retrieve appropriate entity.
$override_type = 'overridden';
$override = $entity_storage
->load($override->entity_id
->getString());
$field = $override
->get($field_name);
// TODO: drill down and retrieve, replace values.
// TODO: drop in the URL to edit.
}
elseif ($override->value
->getString()) {
// Rescheduled, use values from override.
$override_type = 'rescheduled';
// TODO: drill down and retrieve, replace values.
$instance['value'] = $override->value
->getString();
$instance['end_value'] = $override->end_value
->getString();
}
else {
// Cancelled, so change class and actions.
$override_type = 'cancelled';
}
$instance['class'] = $override_type;
$instance['override'] = $override;
}
else {
}
$instance['rrule'] = $this->rrule
->id();
$instance['rrule_index'] = $index;
}
return $this
->render($instances);
}
/**
* Builds the render array for the listings.
*
* @param array $instances
* The data for instances to list.
*
* @return array
* A render array of the list and appropriate actions.
*
* @see \Drupal\Core\Entity\EntityListBuilder::render()
*/
private function render(array $instances) {
$build['table'] = [
'#type' => 'table',
'#attributes' => [
'id' => 'manage-instances',
],
'#header' => $this
->buildHeader(),
'#rows' => [],
'#empty' => $this
->t('There are no @label yet.', [
'@label' => 'recurring instances',
]),
];
foreach ($instances as $index => $instance) {
if ($row = $this
->buildRow($instance)) {
$build['table']['#rows'][$index] = $row;
}
}
$build['table']['#attached']['library'][] = 'smart_date_recur/smart_date_recur';
return $build;
}
/**
* Builds the header row for the listing.
*
* @return array
* A render array structure of header strings.
*/
public function buildHeader() {
$row['label'] = $this
->t('Instance');
$row['operations'] = $this
->t('Operations');
return $row;
}
/**
* Builds a row for an instance in the listing.
*
* @param array $instance
* The data for this row of the list.
*
* @return array
* A render array structure of fields for this entity.
*
* @see \Drupal\Core\Entity\EntityListBuilder::render()
*/
public function buildRow(array $instance) {
// Get format settings.
// TODO: make the choice of format configurable?
$format = \Drupal::getContainer()
->get('entity_type.manager')
->getStorage('smart_date_format')
->load('compact');
$settings = $format
->getOptions();
// Format range for this instance.
$row['label']['data'] = SmartDateTrait::formatSmartDate($instance['value'], $instance['end_value'], $settings);
if (isset($instance['class'])) {
$row['label']['class'][] = 'smart-date-instance--' . $instance['class'];
}
$row['operations']['data'] = $this
->buildOperations($instance);
return $row;
}
/**
* Builds a renderable list of operation links for the entity.
*
* @param array $instance
* The entity on which the linked operations will be performed.
*
* @return array
* A renderable array of operation links.
*/
public function buildOperations(array $instance) {
$build = [
'#type' => 'operations',
'#links' => $this
->getOperations($instance),
];
return $build;
}
/**
* Builds a list of operation links for the entity.
*
* @param array $instance
* The entity on which the linked operations will be performed.
*
* @return array
* A not-yet renderable array of operation links.
*/
public function getOperations(array $instance) {
$operations = [];
// Only one use case doesn't need this, so include by default.
$operations['remove'] = [
'title' => $this
->t('Remove Instance'),
'weight' => 80,
'url' => Url::fromRoute('smart_date_recur.instance.remove', [
'rrule' => $instance['rrule'],
'index' => $instance['rrule_index'],
]),
];
if ($this->useAjax) {
$operations['remove']['url'] = Url::fromRoute('smart_date_recur.instance.remove.ajax', [
'rrule' => $instance['rrule'],
'index' => $instance['rrule_index'],
'confirm' => 0,
]);
$operations['remove']['attributes']['class'][] = 'use-ajax';
}
if (isset($instance['override'])) {
// An override exists, so provide an option to revert (delete) it.
$operations['delete'] = [
'title' => $this
->t('Restore Default'),
'weight' => 100,
'url' => $instance['override']
->toUrl('delete-form'),
];
if ($this->useAjax) {
$operations['delete']['url'] = Url::fromRoute('smart_date_recur.instance.revert.ajax', [
'entity' => $instance['override']
->id(),
'confirm' => 0,
]);
$operations['delete']['attributes']['class'][] = 'use-ajax';
}
switch ($instance['class']) {
case 'cancelled':
// Only option should be to revert.
unset($operations['remove']);
break;
case 'rescheduled':
$operations['edit'] = [
'title' => $this
->t('Reschedule'),
'weight' => 0,
'url' => Url::fromRoute('smart_date_recur.instance.reschedule', [
'rrule' => $instance['rrule'],
'index' => $instance['rrule_index'],
]),
];
if ($this->useAjax) {
$operations['edit']['url'] = Url::fromRoute('smart_date_recur.instance.reschedule.ajax', [
'rrule' => $instance['rrule'],
'index' => $instance['rrule_index'],
]);
$operations['edit']['attributes']['class'][] = 'use-ajax';
}
case 'overriden':
// Removal handled by the delete action already defined.
// TODO: Update the URL of the Edit button above to point to the
// entity form of the referenced entity.
break;
}
}
else {
// Default state, so only options are: create override or cancel.
$operations['create'] = [
'title' => $this
->t('Override'),
'weight' => 10,
'url' => Url::fromRoute('smart_date_recur.instance.reschedule', [
'rrule' => $instance['rrule'],
'index' => $instance['rrule_index'],
]),
];
if ($this->useAjax) {
$operations['create']['url'] = Url::fromRoute('smart_date_recur.instance.reschedule.ajax', [
'rrule' => $instance['rrule'],
'index' => $instance['rrule_index'],
]);
$operations['create']['attributes']['class'][] = 'use-ajax';
}
}
// Sort the operations before returning them.
uasort($operations, '\\Drupal\\Component\\Utility\\SortArray::sortByWeightElement');
return $operations;
}
/**
* Builds a renderable array for an error due to invalid input.
*
* @return array
* A renderable array with the error message.
*/
private function returnError() {
return [
'#type' => 'markup',
'#markup' => t('An invalid value was received.'),
];
}
/**
* Use the overrides for this RRule object to update the parent entity.
*
* @param \Drupal\smart_date_recur\Entity\SmartDateRule $rrule
* The rule whose overrides will be applied to the parent entity.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* A redirect to the view of the parent entity.
*/
public function applyChanges(SmartDateRule $rrule) {
// Get all the necessary data elements from the rrule object.
if (!($entity = $rrule
->getParentEntity())) {
return $this
->returnError();
}
$rid = $rrule
->id();
$field_name = $rrule->field_name
->getString();
// Retrieve all existing values for the field.
$values = $entity
->get($field_name)
->getValue();
$first_instance = FALSE;
// Go through the existing values and remove all this rule's instances.
foreach ($values as $index => $value) {
if ($value['rrule'] == $rid) {
if (!$first_instance) {
// Save the first instance to use as a template.
$first_instance = $value;
}
// Remove all existing values for this rrule, so they can be replaced.
unset($values[$index]);
}
}
// Retrieve all instances for this rule, with overrides applied.
$instances = $rrule
->getRuleInstances();
foreach ($instances as $rrule_index => $instance) {
// Apply instance values to our template, and add to the field values.
$first_instance['value'] = $instance['value'];
$first_instance['end_value'] = $instance['end_value'];
// Calculate the duration, since it isn't returned.
$first_instance['duration'] = ($instance['end_value'] - $instance['value']) / 60;
$first_instance['rrule_index'] = $rrule_index;
$values[] = $first_instance;
}
// Add to the entity, and save.
$entity
->set($field_name, $values);
$entity
->save();
// Redirect to the entity view.
return new RedirectResponse($entity
->toUrl()
->toString());
}
/**
* Removing a rule instance.
*
* @param int $index
* Index of the instance to remove.
* @param int|null $oid
* SmartDateOverride override id if existing.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function removeInstance(int $index, ?int $oid) {
$rrule = $this->rrule
->id();
// Delete existing override, if it exists.
if ($oid) {
$existing = SmartDateOverride::load($oid);
$existing
->delete();
}
$override = SmartDateOverride::create([
'rrule' => $rrule,
'rrule_index' => $index,
]);
$override
->save();
}
/**
* Preparing the form for removing a rule instance via Ajax.
*
* @param \Drupal\smart_date_recur\Entity\SmartDateRule $rrule
* The rule object.
* @param int $index
* Index of the instance to remove.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* The AJAX response object.
*/
public function removeAjax(SmartDateRule $rrule, int $index) {
$this
->setSmartDateRule($rrule);
$this
->setUseAjax(TRUE);
$content = \Drupal::formBuilder()
->getForm(SmartDateRemoveInstanceForm::class, $rrule, $index, TRUE);
$content['title']['#markup'] = '<p>' . $content['#title'] . '</p>';
$form['#attached']['library'][] = 'core/drupal.ajax';
$response = new AjaxResponse();
$response
->addCommand(new ReplaceCommand('#manage-instances', $content));
return $response;
}
/**
* Preparing output of instance listing either modal/Ajax or default.
*
* @param \Drupal\smart_date_recur\Entity\SmartDateRule $rrule
* The rule object.
* @param bool $modal
* Whether or not to use a modal for display.
*
* @return array|\Drupal\Core\Ajax\AjaxResponse
* The AJAX response object.
*/
public function listInstances(SmartDateRule $rrule, bool $modal = FALSE) {
$this
->setSmartDateRule($rrule);
if ($modal) {
$this
->setUseAjax(TRUE);
}
$instancesList = $this
->listInstancesOutput();
if ($modal) {
$response = new AjaxResponse();
$response
->addCommand(new OpenModalDialogCommand('Manage Instances', $instancesList, [
'width' => '800',
]));
return $response;
}
else {
return $instancesList;
}
}
/**
* Reverting a rule instance in an Ajax confirm dialog.
*
* @param \Drupal\smart_date_recur\Entity\SmartDateOverride $entity
* The override entity to remove.
* @param bool $confirm
* Whether or not the removal has been confirmed.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* The AJAX response object.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function revertAjax(SmartDateOverride $entity, bool $confirm) {
if ($confirm) {
$rrule = $this
->entityTypeManager()
->getStorage('smart_date_rule')
->load($entity->rrule->value);
$this
->setSmartDateRule($rrule);
$this
->setUseAjax(TRUE);
$this
->revertInstance($entity);
$content = $this
->listInstancesOutput();
}
else {
$content = \Drupal::formBuilder()
->getForm(SmartDateOverrideDeleteAjaxForm::class, $entity);
}
$form['#attached']['library'][] = 'core/drupal.ajax';
$response = new AjaxResponse();
$response
->addCommand(new ReplaceCommand('#manage-instances', $content));
return $response;
}
/**
* Preparing the form for rescheduling a rule instance via Ajax.
*
* @param \Drupal\smart_date_recur\Entity\SmartDateRule $rrule
* The rule object.
* @param string $index
* Index of the instance to override.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* The AJAX response object.
*/
public function reschedule(SmartDateRule $rrule, string $index) {
$content = \Drupal::formBuilder()
->getForm(SmartDateOverrideForm::class, $rrule, $index, TRUE);
$form['#attached']['library'][] = 'core/drupal.ajax';
$response = new AjaxResponse();
$response
->addCommand(new ReplaceCommand('#manage-instances', $content));
return $response;
}
/**
* Revert instance by deleting the override.
*
* @param \Drupal\smart_date_recur\Entity\SmartDateOverride $entity
* The override entity to remove.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function revertInstance(SmartDateOverride $entity) {
$entity
->delete();
}
/**
* Setting the SmartDateRule on the controller.
*
* @param \Drupal\smart_date_recur\Entity\SmartDateRule $rrule
* The rule object.
*/
public function setSmartDateRule(SmartDateRule $rrule) {
$this->rrule = $rrule;
}
/**
* Setting the use ajax setting on the controller.
*
* @param bool $use_ajax
* Whether or not to use AJAX.
*/
public function setUseAjax(bool $use_ajax) {
$this->useAjax = $use_ajax;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ControllerBase:: |
protected | property | The configuration factory. | |
ControllerBase:: |
protected | property | The current user service. | 1 |
ControllerBase:: |
protected | property | The entity form builder. | |
ControllerBase:: |
protected | property | The form builder. | 2 |
ControllerBase:: |
protected | property | The key-value storage. | 1 |
ControllerBase:: |
protected | property | The language manager. | 1 |
ControllerBase:: |
protected | property | The module handler. | 2 |
ControllerBase:: |
protected | property | The state service. | |
ControllerBase:: |
protected | function | Returns the requested cache bin. | |
ControllerBase:: |
protected | function | Retrieves a configuration object. | |
ControllerBase:: |
private | function | Returns the service container. | |
ControllerBase:: |
public static | function |
Instantiates a new instance of this class. Overrides ContainerInjectionInterface:: |
46 |
ControllerBase:: |
protected | function | Returns the current user. | 1 |
ControllerBase:: |
protected | function | Retrieves the entity form builder. | |
ControllerBase:: |
protected | function | Retrieves the entity type manager. | |
ControllerBase:: |
protected | function | Returns the form builder service. | 2 |
ControllerBase:: |
protected | function | Returns a key/value storage collection. | 1 |
ControllerBase:: |
protected | function | Returns the language manager service. | 1 |
ControllerBase:: |
protected | function | Returns the module handler. | 2 |
ControllerBase:: |
protected | function | Returns a redirect response object for the specified route. | |
ControllerBase:: |
protected | function | Returns the state storage service. | |
Instances:: |
protected | property | The entity type ID. | |
Instances:: |
protected | property |
Information about the entity type. Overrides ControllerBase:: |
|
Instances:: |
protected | property | The rrule object whose instances are being listed. | |
Instances:: |
protected | property | The entity storage class. | |
Instances:: |
private | property | Indicating whether current controller instance uses Ajax. | |
Instances:: |
public | function | Use the overrides for this RRule object to update the parent entity. | |
Instances:: |
public | function | Builds the header row for the listing. | |
Instances:: |
public | function | Builds a renderable list of operation links for the entity. | |
Instances:: |
public | function | Builds a row for an instance in the listing. | |
Instances:: |
public | function | Builds a list of operation links for the entity. | |
Instances:: |
public | function | Preparing output of instance listing either modal/Ajax or default. | |
Instances:: |
public | function | Provide a list of rule items with operations to change rule items. | |
Instances:: |
public | function | Preparing the form for removing a rule instance via Ajax. | |
Instances:: |
public | function | Removing a rule instance. | |
Instances:: |
private | function | Builds the render array for the listings. | |
Instances:: |
public | function | Preparing the form for rescheduling a rule instance via Ajax. | |
Instances:: |
private | function | Builds a renderable array for an error due to invalid input. | |
Instances:: |
public | function | Reverting a rule instance in an Ajax confirm dialog. | |
Instances:: |
public | function | Revert instance by deleting the override. | |
Instances:: |
public | function | Setting the SmartDateRule on the controller. | |
Instances:: |
public | function | Setting the use ajax setting on the controller. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
protected | property | The messenger. | 27 |
MessengerTrait:: |
public | function | Gets the messenger. | 27 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 4 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |