Loading auctioneer.services.yml +4 −1 Changes for auctioneer.services.yml: 4 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -2,6 +2,9 @@ services: plugin.manager.auctioneer.auction_type: class: Drupal\auctioneer\AuctionTypePluginManager parent: default_plugin_manager auctioneer.auction_field.manager: class: Drupal\auctioneer\AuctionFieldManager arguments: ['@entity_type.manager'] auctioneer.auction_type.manager: class: Drupal\auctioneer\AuctionTypeManager arguments: ['@plugin.manager.auctioneer.auction_type', '@entity_type.manager', '@database', '@logger.factory', '@current_user'] arguments: ['@plugin.manager.auctioneer.auction_type', '@entity_type.manager', '@auctioneer.auction_field.manager', '@database', '@logger.factory', '@current_user'] modules/auctioneer_sniper/auctioneer_sniper.info.yml 0 → 100644 +7 −0 Changes for modules/auctioneer_sniper/auctioneer_sniper.info.yml: 7 added lines, 0 removed lines. Original line number Diff line number Diff line name: Auctioneer - Sniper type: module description: 'Auction sniping features for date-ranged auction types.' package: Auctioneer core_version_requirement: ^8.8.8 || ^9 dependencies: - drupal:auctioneer modules/auctioneer_sniper/auctioneer_sniper.module 0 → 100755 +182 −0 Changes for modules/auctioneer_sniper/auctioneer_sniper.module: 182 added lines, 0 removed lines. Original line number Diff line number Diff line <?php /** * @file * Defines the "auctioneer_sniper" primary hooks. */ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; /** * Implements hook_ENTITY_TYPE_insert() for entity type "bid". */ function auctioneer_sniper_bid_insert(EntityInterface $entity) { /** @var \Drupal\auctioneer\Entity\AuctionInterface $auction */ $auction = $entity->getAuction(); if ($auction) { \Drupal::service('auctioneer_sniper.manager')->requestAuctionLifetimeUpdate($auction); } } /** * Implements hook_form_BASE_FORM_ID_alter() for "auction_type_form". */ function auctioneer_sniper_form_auction_type_form_alter(&$form, FormStateInterface $form_state, $form_id) { $auction_type = $form_state->getFormObject()->getEntity(); $form['sniper'] = [ '#type' => 'details', '#title' => t('Sniping options'), '#open' => TRUE, '#weight' => 10, '#tree' => TRUE, ]; if (\Drupal::service('auctioneer_sniper.manager')->auctionTypeIsDateRangeInstance($auction_type)) { $sniper = $auction_type->getThirdPartySetting('auctioneer_sniper', 'settings'); $form['sniper']['enable'] = [ '#type' => 'checkbox', '#title' => t('Enable for this auction type'), '#default_value' => !empty($sniper) && $sniper['enable'] ?? FALSE, ]; $form['actions']['submit']['#submit'][] = '_auctioneer_sniper_form_auction_type_form_submit'; } else { if ($form_id == 'auction_type_add_form') { $message = t('You need to save this auction type before enabling this feature.'); } else { $message = t('This auction type does not support sniping features. It does not implement interface <em>@interface</em>.', [ '@interface' => 'Drupal\auctioneer\Plugin\Auctioneer\AuctionType\DateRangeAuctionTypeInterface', ]); } $form['sniper']['info'] = [ '#type' => 'html_tag', '#tag' => 'p', '#value' => $message, ]; } } /** * Custom submit function to set sniping configurations. */ function _auctioneer_sniper_form_auction_type_form_submit(array $form, FormStateInterface $form_state) { $sniper = $form_state->getValue('sniper'); $auction_type = $form_state->getFormObject()->getEntity(); // Saving our configurations. $settings = [ 'enable' => (bool) $sniper['enable'], ]; $auction_type->setThirdPartySetting('auctioneer_sniper', 'settings', $settings); $auction_type->save(); } /** * Implements hook_ENTITY_TYPE_insert() for entity type "auction_type". */ function auctioneer_sniper_auction_type_insert(EntityInterface $entity) { auctioneer_sniper_auction_type_post_save($entity); } /** * Implements hook_ENTITY_TYPE_update() for entity type "auction_type". */ function auctioneer_sniper_auction_type_update(EntityInterface $entity) { auctioneer_sniper_auction_type_post_save($entity); } /** * Helper function to provide auction type sniping features. */ function auctioneer_sniper_auction_type_post_save(EntityInterface $entity) { $settings = $entity->getThirdPartySetting('auctioneer_sniper', 'settings'); if (!empty($settings) && isset($settings['enable']) && (bool) $settings['enable']) { \Drupal::service('auctioneer_sniper.manager')->initializeAuctionTypeSniperConfigurations($entity); } } /** * Implements hook_form_BASE_FORM_ID_alter() for 'auction_form'. */ function auctioneer_sniper_form_auction_form_alter(&$form, FormStateInterface $form_state) { $auction = $form_state->getFormObject()->getEntity(); $auction_type = \Drupal::entityTypeManager()->getStorage('auction_type')->load($auction->bundle()); $settings = $auction_type->getThirdPartySetting('auctioneer_sniper', 'settings'); if ( !\Drupal::service('auctioneer_sniper.manager')->auctionTypeIsDateRangeInstance($auction_type) || empty($settings) ) { return; } // Let's tweak form fields for better understanding. $groups = [ 'auctioneer_sniper' => [ 'title' => t('Sniping options'), 'description' => t('Sniping prevention options.'), 'field_names' => [ 'auction_sniper_control_enable', ], 'field_counts' => 0, 'weight' => 100, ], 'auctioneer_sniper_threshold' => [ 'title' => t('Threshold'), 'description' => t('Once auction reaches the remaining time specified here, then auction lifetime will be increased.'), 'field_names' => [ 'auction_sniper_threshold_amount', 'auction_sniper_threshold_unit', ], 'field_counts' => 0, 'group' => 'auctioneer_sniper', 'weight' => 110, 'states' => [ 'visible' => [ ':input[name="auction_sniper_control_enable[value]"]' => ['checked' => TRUE], ], ], ], 'auctioneer_sniper_increment' => [ 'title' => t('Increment'), 'description' => t('The time to increment auction lifetime once threshold is reached.'), 'field_names' => [ 'auction_sniper_increase_amount', 'auction_sniper_increase_unit', ], 'field_counts' => 0, 'group' => 'auctioneer_sniper', 'weight' => 120, 'states' => [ 'visible' => [ ':input[name="auction_sniper_control_enable[value]"]' => ['checked' => TRUE], ], ], ], ]; foreach ($groups as $group_name => $group_elements) { $form[$group_name] = [ '#title' => $group_elements['title'], '#type' => 'details', '#collapsible' => TRUE, '#weight' => $group_elements['weight'], '#open' => TRUE, '#tree' => FALSE, '#description' => $group_elements['description'], ]; if (isset($group_elements['group'])) { $form[$group_name]['#group'] = $group_elements['group']; } if (isset($group_elements['states'])) { $form[$group_name]['#states'] = $group_elements['states']; } foreach ($group_elements['field_names'] as $field_name) { if (isset($form[$field_name])) { $form[$field_name]['#group'] = $group_name; // Let's keep count of fields, to know if group should be available. $groups[$group_name]['field_counts']++; } } if ($groups[$group_name]['field_counts'] == 0 || !$settings['enable']) { $form[$group_name]['#access'] = FALSE; } } } modules/auctioneer_sniper/auctioneer_sniper.services.yml 0 → 100755 +4 −0 Changes for modules/auctioneer_sniper/auctioneer_sniper.services.yml: 4 added lines, 0 removed lines. Original line number Diff line number Diff line services: auctioneer_sniper.manager: class: Drupal\auctioneer_sniper\AuctionSniperManager arguments: ['@auctioneer.auction_type.manager'] modules/auctioneer_sniper/src/AuctionSniperManager.php 0 → 100644 +202 −0 Changes for modules/auctioneer_sniper/src/AuctionSniperManager.php: 202 added lines, 0 removed lines. Original line number Diff line number Diff line <?php namespace Drupal\auctioneer_sniper; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; use Drupal\auctioneer\AuctionTypeManagerInterface; use Drupal\auctioneer\Entity\AuctionInterface; use Drupal\auctioneer\Entity\AuctionTypeInterface; /** * Provides managing service for auction sniping operations. */ class AuctionSniperManager implements AuctionSniperManagerInterface { use StringTranslationTrait; /** * The auction type manager. * * @var \Drupal\auctioneer\AuctionTypeManagerInterface */ protected $auctionTypeManager; /** * Constructor method. * * @param \Drupal\auctioneer\AuctionTypeManagerInterface $auction_type_manager * The auction type manager. */ public function __construct(AuctionTypeManagerInterface $auction_type_manager) { $this->auctionTypeManager = $auction_type_manager; } /** * {@inheritdoc} */ public function initializeAuctionTypeSniperConfigurations(AuctionTypeInterface $auction_type, bool $lock_fields = TRUE) { if (!$this->auctionTypeIsDateRangeInstance($auction_type)) { // Don't allow initializing settings to the unsupported auction types. return; } $fields = [ 'auction_sniper_control_enable' => BaseFieldDefinition::create('boolean') ->setLabel($this->t('Enable sniping prevention')) ->setDisplayOptions('form', [ 'type' => 'boolean_checkbox', 'settings' => [ 'display_label' => TRUE, ], ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE), 'auction_sniper_threshold_amount' => BaseFieldDefinition::create('integer') ->setLabel($this->t('Amount')) ->setDisplayOptions('form', [ 'type' => 'number', ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE), 'auction_sniper_threshold_unit' => BaseFieldDefinition::create('list_string') ->setLabel($this->t('Unit')) ->setSettings([ 'allowed_values_function' => '\Drupal\auctioneer_sniper\AuctionSniperManager::getSnipingAllowedDateUnits', ]) ->setDisplayOptions('form', [ 'type' => 'options_select', ]) ->setDisplayConfigurable('view', TRUE) ->setDisplayConfigurable('form', TRUE), 'auction_sniper_increase_amount' => BaseFieldDefinition::create('integer') ->setLabel($this->t('Amount')) ->setDisplayOptions('form', [ 'type' => 'number', ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE), 'auction_sniper_increase_unit' => BaseFieldDefinition::create('list_string') ->setLabel($this->t('Unit')) ->setSettings([ 'allowed_values_function' => '\Drupal\auctioneer_sniper\AuctionSniperManager::getSnipingAllowedDateUnits', ]) ->setDisplayOptions('form', [ 'type' => 'options_select', ]) ->setDisplayConfigurable('view', TRUE) ->setDisplayConfigurable('form', TRUE), ]; $auction_field_manager = $this->auctionTypeManager->getAuctionFieldManager(); $auction_field_manager->provideEntityTypeFields($fields, 'auction', $auction_type->id(), $lock_fields); } /** * {@inheritdoc} */ public static function getSnipingAllowedDateUnits() : array { // Does anyone really need seconds? return [ 'minutes' => t('Minutes'), 'hours' => t('Hours'), 'days' => t('Days'), 'weeks' => t('Weeks'), 'months' => t('Months'), 'years' => t('Years'), ]; } /** * {@inheritdoc} */ public function auctionTypeIsDateRangeInstance(AuctionTypeInterface $auction_type) : bool { $bid_type = $auction_type->getBidType(); $plugin_definition = $bid_type ? $this->auctionTypeManager->getBidTypePluginDefinition($bid_type) : []; if (isset($plugin_definition['class'])) { $reflection = new \ReflectionClass($plugin_definition['class']); return $reflection->implementsInterface('\Drupal\auctioneer\AuctionTypeDateRangeInterface'); } return FALSE; } /** * {@inheritdoc} */ public function requestAuctionLifetimeUpdate(AuctionInterface $auction) { $auction_type = $auction->getAuctionType(); if (!$this->auctionTypeIsDateRangeInstance($auction_type)) { return; } if ( !$auction->hasField('auction_sniper_control_enable') || !$auction->hasField('auction_sniper_threshold_amount') || !$auction->hasField('auction_sniper_threshold_unit') || !$auction->hasField('auction_sniper_increase_amount') || !$auction->hasField('auction_sniper_increase_unit') ) { return; } $settings = $auction_type->getThirdPartySetting('auctioneer_sniper', 'settings'); $enable = (bool) $auction->get('auction_sniper_control_enable')->getString(); if (!$enable || (!empty($settings) && isset($settings['enable']) && !(bool) $settings['enable'])) { return; } // Only update if entity has this feature enabled. $t_amount = intval($auction->get('auction_sniper_threshold_amount')->getString()); $t_unit = $auction->get('auction_sniper_threshold_unit')->getString(); $i_amount = intval($auction->get('auction_sniper_increase_amount')->getString()); $i_unit = $auction->get('auction_sniper_increase_unit')->getString(); if ($t_amount && $t_unit && $i_amount && $i_unit) { $bid_type = $auction_type->getBidType(); // Our plugin instance. $plugin_instance = $this->auctionTypeManager->getAuctionPluginManager()->createInstance($bid_type->getPluginName()); if ($plugin_instance) { $now_date = new DrupalDateTime(); $auction_dates = $plugin_instance->requestAuctionDates($auction); $new_values = []; foreach ($auction_dates as $field_name => $date_range_items) { if (!$auction->hasField($field_name)) { continue; } $date_range_items = is_array($date_range_items) ? $date_range_items : [$date_range_items]; $delta = 0; foreach ($date_range_items as $date_range_item) { if ($date_range_item instanceof DateRangeItem) { $start_date = $date_range_item->start_date; $end_date = $date_range_item->end_date; // Calculated auction dates. $t_date = clone $end_date; $t_date->modify("-$t_amount $t_unit"); if ($now_date >= $t_date) { $i_date = clone $end_date; $i_date->modify("+$i_amount $i_unit"); // Saving new dates into a temporal array, to update later. $new_values[$field_name][$delta] = [ 'value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), 'end_value' => $i_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), ]; } $delta++; } } } // Now, let's set updated dates. We support update by delta. if (!empty($new_values)) { foreach ($new_values as $field_name => $values) { foreach ($values as $delta => $value) { $auction->{$field_name}[$delta] = $value; } } $auction->save(); } } } return $auction; } } Loading
auctioneer.services.yml +4 −1 Changes for auctioneer.services.yml: 4 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -2,6 +2,9 @@ services: plugin.manager.auctioneer.auction_type: class: Drupal\auctioneer\AuctionTypePluginManager parent: default_plugin_manager auctioneer.auction_field.manager: class: Drupal\auctioneer\AuctionFieldManager arguments: ['@entity_type.manager'] auctioneer.auction_type.manager: class: Drupal\auctioneer\AuctionTypeManager arguments: ['@plugin.manager.auctioneer.auction_type', '@entity_type.manager', '@database', '@logger.factory', '@current_user'] arguments: ['@plugin.manager.auctioneer.auction_type', '@entity_type.manager', '@auctioneer.auction_field.manager', '@database', '@logger.factory', '@current_user']
modules/auctioneer_sniper/auctioneer_sniper.info.yml 0 → 100644 +7 −0 Changes for modules/auctioneer_sniper/auctioneer_sniper.info.yml: 7 added lines, 0 removed lines. Original line number Diff line number Diff line name: Auctioneer - Sniper type: module description: 'Auction sniping features for date-ranged auction types.' package: Auctioneer core_version_requirement: ^8.8.8 || ^9 dependencies: - drupal:auctioneer
modules/auctioneer_sniper/auctioneer_sniper.module 0 → 100755 +182 −0 Changes for modules/auctioneer_sniper/auctioneer_sniper.module: 182 added lines, 0 removed lines. Original line number Diff line number Diff line <?php /** * @file * Defines the "auctioneer_sniper" primary hooks. */ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; /** * Implements hook_ENTITY_TYPE_insert() for entity type "bid". */ function auctioneer_sniper_bid_insert(EntityInterface $entity) { /** @var \Drupal\auctioneer\Entity\AuctionInterface $auction */ $auction = $entity->getAuction(); if ($auction) { \Drupal::service('auctioneer_sniper.manager')->requestAuctionLifetimeUpdate($auction); } } /** * Implements hook_form_BASE_FORM_ID_alter() for "auction_type_form". */ function auctioneer_sniper_form_auction_type_form_alter(&$form, FormStateInterface $form_state, $form_id) { $auction_type = $form_state->getFormObject()->getEntity(); $form['sniper'] = [ '#type' => 'details', '#title' => t('Sniping options'), '#open' => TRUE, '#weight' => 10, '#tree' => TRUE, ]; if (\Drupal::service('auctioneer_sniper.manager')->auctionTypeIsDateRangeInstance($auction_type)) { $sniper = $auction_type->getThirdPartySetting('auctioneer_sniper', 'settings'); $form['sniper']['enable'] = [ '#type' => 'checkbox', '#title' => t('Enable for this auction type'), '#default_value' => !empty($sniper) && $sniper['enable'] ?? FALSE, ]; $form['actions']['submit']['#submit'][] = '_auctioneer_sniper_form_auction_type_form_submit'; } else { if ($form_id == 'auction_type_add_form') { $message = t('You need to save this auction type before enabling this feature.'); } else { $message = t('This auction type does not support sniping features. It does not implement interface <em>@interface</em>.', [ '@interface' => 'Drupal\auctioneer\Plugin\Auctioneer\AuctionType\DateRangeAuctionTypeInterface', ]); } $form['sniper']['info'] = [ '#type' => 'html_tag', '#tag' => 'p', '#value' => $message, ]; } } /** * Custom submit function to set sniping configurations. */ function _auctioneer_sniper_form_auction_type_form_submit(array $form, FormStateInterface $form_state) { $sniper = $form_state->getValue('sniper'); $auction_type = $form_state->getFormObject()->getEntity(); // Saving our configurations. $settings = [ 'enable' => (bool) $sniper['enable'], ]; $auction_type->setThirdPartySetting('auctioneer_sniper', 'settings', $settings); $auction_type->save(); } /** * Implements hook_ENTITY_TYPE_insert() for entity type "auction_type". */ function auctioneer_sniper_auction_type_insert(EntityInterface $entity) { auctioneer_sniper_auction_type_post_save($entity); } /** * Implements hook_ENTITY_TYPE_update() for entity type "auction_type". */ function auctioneer_sniper_auction_type_update(EntityInterface $entity) { auctioneer_sniper_auction_type_post_save($entity); } /** * Helper function to provide auction type sniping features. */ function auctioneer_sniper_auction_type_post_save(EntityInterface $entity) { $settings = $entity->getThirdPartySetting('auctioneer_sniper', 'settings'); if (!empty($settings) && isset($settings['enable']) && (bool) $settings['enable']) { \Drupal::service('auctioneer_sniper.manager')->initializeAuctionTypeSniperConfigurations($entity); } } /** * Implements hook_form_BASE_FORM_ID_alter() for 'auction_form'. */ function auctioneer_sniper_form_auction_form_alter(&$form, FormStateInterface $form_state) { $auction = $form_state->getFormObject()->getEntity(); $auction_type = \Drupal::entityTypeManager()->getStorage('auction_type')->load($auction->bundle()); $settings = $auction_type->getThirdPartySetting('auctioneer_sniper', 'settings'); if ( !\Drupal::service('auctioneer_sniper.manager')->auctionTypeIsDateRangeInstance($auction_type) || empty($settings) ) { return; } // Let's tweak form fields for better understanding. $groups = [ 'auctioneer_sniper' => [ 'title' => t('Sniping options'), 'description' => t('Sniping prevention options.'), 'field_names' => [ 'auction_sniper_control_enable', ], 'field_counts' => 0, 'weight' => 100, ], 'auctioneer_sniper_threshold' => [ 'title' => t('Threshold'), 'description' => t('Once auction reaches the remaining time specified here, then auction lifetime will be increased.'), 'field_names' => [ 'auction_sniper_threshold_amount', 'auction_sniper_threshold_unit', ], 'field_counts' => 0, 'group' => 'auctioneer_sniper', 'weight' => 110, 'states' => [ 'visible' => [ ':input[name="auction_sniper_control_enable[value]"]' => ['checked' => TRUE], ], ], ], 'auctioneer_sniper_increment' => [ 'title' => t('Increment'), 'description' => t('The time to increment auction lifetime once threshold is reached.'), 'field_names' => [ 'auction_sniper_increase_amount', 'auction_sniper_increase_unit', ], 'field_counts' => 0, 'group' => 'auctioneer_sniper', 'weight' => 120, 'states' => [ 'visible' => [ ':input[name="auction_sniper_control_enable[value]"]' => ['checked' => TRUE], ], ], ], ]; foreach ($groups as $group_name => $group_elements) { $form[$group_name] = [ '#title' => $group_elements['title'], '#type' => 'details', '#collapsible' => TRUE, '#weight' => $group_elements['weight'], '#open' => TRUE, '#tree' => FALSE, '#description' => $group_elements['description'], ]; if (isset($group_elements['group'])) { $form[$group_name]['#group'] = $group_elements['group']; } if (isset($group_elements['states'])) { $form[$group_name]['#states'] = $group_elements['states']; } foreach ($group_elements['field_names'] as $field_name) { if (isset($form[$field_name])) { $form[$field_name]['#group'] = $group_name; // Let's keep count of fields, to know if group should be available. $groups[$group_name]['field_counts']++; } } if ($groups[$group_name]['field_counts'] == 0 || !$settings['enable']) { $form[$group_name]['#access'] = FALSE; } } }
modules/auctioneer_sniper/auctioneer_sniper.services.yml 0 → 100755 +4 −0 Changes for modules/auctioneer_sniper/auctioneer_sniper.services.yml: 4 added lines, 0 removed lines. Original line number Diff line number Diff line services: auctioneer_sniper.manager: class: Drupal\auctioneer_sniper\AuctionSniperManager arguments: ['@auctioneer.auction_type.manager']
modules/auctioneer_sniper/src/AuctionSniperManager.php 0 → 100644 +202 −0 Changes for modules/auctioneer_sniper/src/AuctionSniperManager.php: 202 added lines, 0 removed lines. Original line number Diff line number Diff line <?php namespace Drupal\auctioneer_sniper; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; use Drupal\auctioneer\AuctionTypeManagerInterface; use Drupal\auctioneer\Entity\AuctionInterface; use Drupal\auctioneer\Entity\AuctionTypeInterface; /** * Provides managing service for auction sniping operations. */ class AuctionSniperManager implements AuctionSniperManagerInterface { use StringTranslationTrait; /** * The auction type manager. * * @var \Drupal\auctioneer\AuctionTypeManagerInterface */ protected $auctionTypeManager; /** * Constructor method. * * @param \Drupal\auctioneer\AuctionTypeManagerInterface $auction_type_manager * The auction type manager. */ public function __construct(AuctionTypeManagerInterface $auction_type_manager) { $this->auctionTypeManager = $auction_type_manager; } /** * {@inheritdoc} */ public function initializeAuctionTypeSniperConfigurations(AuctionTypeInterface $auction_type, bool $lock_fields = TRUE) { if (!$this->auctionTypeIsDateRangeInstance($auction_type)) { // Don't allow initializing settings to the unsupported auction types. return; } $fields = [ 'auction_sniper_control_enable' => BaseFieldDefinition::create('boolean') ->setLabel($this->t('Enable sniping prevention')) ->setDisplayOptions('form', [ 'type' => 'boolean_checkbox', 'settings' => [ 'display_label' => TRUE, ], ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE), 'auction_sniper_threshold_amount' => BaseFieldDefinition::create('integer') ->setLabel($this->t('Amount')) ->setDisplayOptions('form', [ 'type' => 'number', ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE), 'auction_sniper_threshold_unit' => BaseFieldDefinition::create('list_string') ->setLabel($this->t('Unit')) ->setSettings([ 'allowed_values_function' => '\Drupal\auctioneer_sniper\AuctionSniperManager::getSnipingAllowedDateUnits', ]) ->setDisplayOptions('form', [ 'type' => 'options_select', ]) ->setDisplayConfigurable('view', TRUE) ->setDisplayConfigurable('form', TRUE), 'auction_sniper_increase_amount' => BaseFieldDefinition::create('integer') ->setLabel($this->t('Amount')) ->setDisplayOptions('form', [ 'type' => 'number', ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE), 'auction_sniper_increase_unit' => BaseFieldDefinition::create('list_string') ->setLabel($this->t('Unit')) ->setSettings([ 'allowed_values_function' => '\Drupal\auctioneer_sniper\AuctionSniperManager::getSnipingAllowedDateUnits', ]) ->setDisplayOptions('form', [ 'type' => 'options_select', ]) ->setDisplayConfigurable('view', TRUE) ->setDisplayConfigurable('form', TRUE), ]; $auction_field_manager = $this->auctionTypeManager->getAuctionFieldManager(); $auction_field_manager->provideEntityTypeFields($fields, 'auction', $auction_type->id(), $lock_fields); } /** * {@inheritdoc} */ public static function getSnipingAllowedDateUnits() : array { // Does anyone really need seconds? return [ 'minutes' => t('Minutes'), 'hours' => t('Hours'), 'days' => t('Days'), 'weeks' => t('Weeks'), 'months' => t('Months'), 'years' => t('Years'), ]; } /** * {@inheritdoc} */ public function auctionTypeIsDateRangeInstance(AuctionTypeInterface $auction_type) : bool { $bid_type = $auction_type->getBidType(); $plugin_definition = $bid_type ? $this->auctionTypeManager->getBidTypePluginDefinition($bid_type) : []; if (isset($plugin_definition['class'])) { $reflection = new \ReflectionClass($plugin_definition['class']); return $reflection->implementsInterface('\Drupal\auctioneer\AuctionTypeDateRangeInterface'); } return FALSE; } /** * {@inheritdoc} */ public function requestAuctionLifetimeUpdate(AuctionInterface $auction) { $auction_type = $auction->getAuctionType(); if (!$this->auctionTypeIsDateRangeInstance($auction_type)) { return; } if ( !$auction->hasField('auction_sniper_control_enable') || !$auction->hasField('auction_sniper_threshold_amount') || !$auction->hasField('auction_sniper_threshold_unit') || !$auction->hasField('auction_sniper_increase_amount') || !$auction->hasField('auction_sniper_increase_unit') ) { return; } $settings = $auction_type->getThirdPartySetting('auctioneer_sniper', 'settings'); $enable = (bool) $auction->get('auction_sniper_control_enable')->getString(); if (!$enable || (!empty($settings) && isset($settings['enable']) && !(bool) $settings['enable'])) { return; } // Only update if entity has this feature enabled. $t_amount = intval($auction->get('auction_sniper_threshold_amount')->getString()); $t_unit = $auction->get('auction_sniper_threshold_unit')->getString(); $i_amount = intval($auction->get('auction_sniper_increase_amount')->getString()); $i_unit = $auction->get('auction_sniper_increase_unit')->getString(); if ($t_amount && $t_unit && $i_amount && $i_unit) { $bid_type = $auction_type->getBidType(); // Our plugin instance. $plugin_instance = $this->auctionTypeManager->getAuctionPluginManager()->createInstance($bid_type->getPluginName()); if ($plugin_instance) { $now_date = new DrupalDateTime(); $auction_dates = $plugin_instance->requestAuctionDates($auction); $new_values = []; foreach ($auction_dates as $field_name => $date_range_items) { if (!$auction->hasField($field_name)) { continue; } $date_range_items = is_array($date_range_items) ? $date_range_items : [$date_range_items]; $delta = 0; foreach ($date_range_items as $date_range_item) { if ($date_range_item instanceof DateRangeItem) { $start_date = $date_range_item->start_date; $end_date = $date_range_item->end_date; // Calculated auction dates. $t_date = clone $end_date; $t_date->modify("-$t_amount $t_unit"); if ($now_date >= $t_date) { $i_date = clone $end_date; $i_date->modify("+$i_amount $i_unit"); // Saving new dates into a temporal array, to update later. $new_values[$field_name][$delta] = [ 'value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), 'end_value' => $i_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), ]; } $delta++; } } } // Now, let's set updated dates. We support update by delta. if (!empty($new_values)) { foreach ($new_values as $field_name => $values) { foreach ($values as $delta => $value) { $auction->{$field_name}[$delta] = $value; } } $auction->save(); } } } return $auction; } }