/** * Constructs the ImageToolkitManager object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The config factory. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. * @param \Drupal\Core\ImageToolkit\ImageToolkitOperationManagerInterface $operation_manager * The toolkit operation manager. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, ImageToolkitOperationManagerInterface $operation_manager) { parent::__construct('Plugin/ImageToolkit', $namespaces, $module_handler, 'Drupal\\Core\\ImageToolkit\\Annotation\\ImageToolkit'); $this->setCacheBackend($cache_backend, 'image_toolkit_plugins'); $this->configFactory = $config_factory; $this->operationManager = $operation_manager; }
/** * Constructs a MigratePluginManager object. * * @param string $type * The type of the plugin: row, source, process, destination, entity_field, * id_map. * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. * @param string $annotation * The annotation class name. */ public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, $annotation = 'Drupal\\Component\\Annotation\\PluginID') { $plugin_interface = isset($plugin_interface_map[$type]) ? $plugin_interface_map[$type] : NULL; parent::__construct("Plugin/migrate/{$type}", $namespaces, $module_handler, $plugin_interface, $annotation); $this->alterInfo('migrate_' . $type . '_info'); $this->setCacheBackend($cache_backend, 'migrate_plugins_' . $type); }
/** * Overrides PluginManagerBase::createInstance(). * * This method is overridden to set the request object when the resource * object is instantiated. */ public function createInstance($plugin_id, array $configuration = array()) { /* @var ResourceInterface $resource */ $resource = parent::createInstance($plugin_id, $configuration); $resource->setRequest($this->request); return $resource; }
/** * Constructs a new instance. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The config factory. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory) { parent::__construct('Plugin/Currency/AmountFormatter', $namespaces, $module_handler, AmountFormatterInterface::class, CurrencyAmountFormatter::class); $this->alterInfo('currency_amount_formatter'); $this->setCacheBackend($cache_backend, 'currency_amount_formatter'); $this->configFactory = $config_factory; }
/** * Constructs the MailManager object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The configuration factory. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory) { parent::__construct('Plugin/Mail', $namespaces, $module_handler, 'Drupal\\Core\\Annotation\\Mail'); $this->alterInfo('mail_backend_info'); $this->setCacheBackend($cache_backend, 'mail_backend_plugins'); $this->mailConfig = $config_factory->get('system.mail'); }
/** * Constructs a new instance. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver * The class_resolver. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ClassResolverInterface $class_resolver) { parent::__construct('Plugin/Payment/Method', $namespaces, $module_handler, PaymentMethodInterface::class, PaymentMethod::class); $this->alterInfo('payment_method'); $this->setCacheBackend($cache_backend, 'payment_method', ['payment_method']); $this->classResolver = $class_resolver; }
/** * Overrides \Drupal\Component\Plugin\PluginManagerBase::__construct(). * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { parent::__construct('Plugin/Validation/Constraint', $namespaces, $module_handler); $this->discovery = new StaticDiscoveryDecorator($this->discovery, array($this, 'registerDefinitions')); $this->alterInfo('validation_constraint'); $this->setCacheBackend($cache_backend, 'validation_constraint_plugins'); }
/** * Constructs a CheckoutPaneManager object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations, * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { parent::__construct('Plugin/Ubercart/CheckoutPane', $namespaces, $module_handler, CheckoutPanePluginInterface::class, CheckoutPane::class); $this->alterInfo('payment_method'); $this->setCacheBackend($cache_backend, 'uc_checkout_panes'); $this->paneConfig = \Drupal::config('uc_cart.settings')->get('panes'); }
/** * Constructs a new ZoneMemberManager. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cacheBackend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler * The module handler. * @param \Drupal\Component\Uuid\UuidInterface $uuidService * The uuid service. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cacheBackend, ModuleHandlerInterface $moduleHandler, UuidInterface $uuidService) { parent::__construct('Plugin/ZoneMember', $namespaces, $moduleHandler, 'Drupal\\address\\Plugin\\ZoneMember\\ZoneMemberInterface', 'Drupal\\address\\Annotation\\ZoneMember'); $this->alterInfo('zone_member_info'); $this->setCacheBackend($cacheBackend, 'zone_member_plugins'); $this->uuidService = $uuidService; }
/** * Constructs a AggregatorPluginManager object. * * @param string $type * The plugin type, for example fetcher. * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. */ public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { $type_annotations = array('fetcher' => 'Drupal\\aggregator\\Annotation\\AggregatorFetcher', 'parser' => 'Drupal\\aggregator\\Annotation\\AggregatorParser', 'processor' => 'Drupal\\aggregator\\Annotation\\AggregatorProcessor'); $plugin_interfaces = array('fetcher' => 'Drupal\\aggregator\\Plugin\\FetcherInterface', 'parser' => 'Drupal\\aggregator\\Plugin\\ParserInterface', 'processor' => 'Drupal\\aggregator\\Plugin\\ProcessorInterface'); parent::__construct("Plugin/aggregator/{$type}", $namespaces, $module_handler, $plugin_interfaces[$type], $type_annotations[$type]); $this->setCacheBackend($cache_backend, 'aggregator_' . $type . '_plugins'); }
/** * {@inheritdoc} */ public function processDefinition(&$definition, $plugin_id) { parent::processDefinition($definition, $plugin_id); if (!isset($definition['list_class'])) { $definition['list_class'] = '\\Drupal\\Core\\Field\\FieldItemList'; } }
/** * Constructs the ImageToolkitOperationManager object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. * @param \Psr\Log\LoggerInterface $logger * A logger instance. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, LoggerInterface $logger) { parent::__construct('Plugin/ImageToolkit/Operation', $namespaces, $module_handler, 'Drupal\\Core\\ImageToolkit\\ImageToolkitOperationInterface', 'Drupal\\Core\\ImageToolkit\\Annotation\\ImageToolkitOperation'); $this->alterInfo('image_toolkit_operation'); $this->setCacheBackend($cache_backend, 'image_toolkit_operation_plugins'); $this->logger = $logger; }
/** * Creates the discovery object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { // We replace the $subdir parameter with our own value. // This tells the plugin system to look for plugins in the 'Plugin/Sandwich' // subfolder inside modules' 'src' folder. $subdir = 'Plugin/Sandwich'; // The name of the interface that plugins should adhere to. Drupal will // enforce this as a requirement. If a plugin does not implement this // interface, than Drupal will throw an error. $plugin_interface = 'Drupal\\plugin_type_example\\SandwichInterface'; // The name of the annotation class that contains the plugin definition. $plugin_definition_annotation_name = 'Drupal\\Component\\Annotation\\Plugin'; parent::__construct($subdir, $namespaces, $module_handler, $plugin_interface, $plugin_definition_annotation_name); // This allows the plugin definitions to be altered by an alter hook. The // parameter defines the name of the hook, thus: hook_sandwich_info_alter(). // In this example, we implement this hook to change the plugin definitions: // see plugin_type_example_sandwich_info_alter(). $this->alterInfo('sandwich_info'); // This sets the caching method for our plugin definitions. Plugin // definitions are cached using the provided cache backend. For our // Sandwich plugin type, we've specified the @cache.default service be used // in the plugin_type_example.services.yml file. The second argument is a // cache key prefix. Out of the box Drupal with the default cache backend // setup will store our plugin definition in the cache_default table using // the sandwich_info key. All that is implementation details however, // all we care about it that caching for our plugin definition is taken // care of by this call. $this->setCacheBackend($cache_backend, 'sandwich_info'); }
/** * Constructs a FormatterPluginManager object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager * The 'field type' plugin manager. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, FieldTypePluginManagerInterface $field_type_manager) { parent::__construct('Plugin/Field/FieldFormatter', $namespaces, $module_handler, 'Drupal\\Core\\Field\\FormatterInterface', 'Drupal\\Core\\Field\\Annotation\\FieldFormatter'); $this->setCacheBackend($cache_backend, 'field_formatter_types_plugins'); $this->alterInfo('field_formatter_info'); $this->fieldTypeManager = $field_type_manager; }
/** * Constructs a new instance. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver * The class resolver. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ClassResolverInterface $class_resolver) { parent::__construct('Plugin/Currency/ExchangeRateProvider', $namespaces, $module_handler, ExchangeRateProviderInterface::class, CurrencyExchangeRateProvider::class); $this->alterInfo('currency_exchange_rate_provider'); $this->setCacheBackend($cache_backend, 'currency_exchange_rate_provider'); $this->classResolver = $class_resolver; }
/** * Constructs a PanelsStorageManager. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. * @param \Drupal\Core\Session\AccountProxyInterface $current_user * The current user service. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, AccountProxyInterface $current_user) { parent::__construct('Plugin/PanelsStorage', $namespaces, $module_handler, PanelsStorageInterface::class, PanelsStorage::class); $this->currentUser = $current_user; $this->alterInfo('panels_storage_info'); $this->setCacheBackend($cache_backend, 'panels_storage'); }
/** * {@inheritdoc} */ public function createInstance($plugin_id, array $configuration = []) { if (!$this->isPluginSupported($plugin_id)) { $plugin_id = $this->getFallbackPluginId($plugin_id); } return parent::createInstance($plugin_id, $configuration); }
/** * {@inheritdoc} */ protected function findDefinitions() { $definitions = parent::findDefinitions(); // Sort definitions by weight uasort($definitions, array('Drupal\\Component\\Utility\\SortArray', 'sortByWeightElement')); return $definitions; }
/** * Constructs a ProcessorPluginManager object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. * @param \Drupal\Core\StringTranslation\TranslationInterface $translation * The string translation manager. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, TranslationInterface $translation) { parent::__construct('Plugin/search_api/processor', $namespaces, $module_handler, 'Drupal\\search_api\\Processor\\ProcessorInterface', 'Drupal\\search_api\\Annotation\\SearchApiProcessor'); $this->setCacheBackend($cache_backend, 'search_api_processors'); $this->alterInfo('search_api_processor_info'); $this->setStringTranslation($translation); }
/** * {@inheritdoc} */ protected function getDiscovery() { if (!isset($this->discovery)) { $this->discovery = parent::getDiscovery(); $this->discovery = new StaticDiscoveryDecorator($this->discovery, [$this, 'registerDefinitions']); } return $this->discovery; }
/** * Constructs a MigratePluginManager object. * * @param string $type * The type of the plugin: row, source, process, destination, entity_field, * id_map. * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. * @param string $annotation * The annotation class name. */ public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, $annotation = 'Drupal\\Component\\Annotation\\PluginID') { $plugin_interface_map = array('destination' => 'Drupal\\migrate\\Plugin\\MigrateDestinationInterface', 'process' => 'Drupal\\migrate\\Plugin\\MigrateProcessInterface', 'source' => 'Drupal\\migrate\\Plugin\\MigrateSourceInterface', 'id_map' => 'Drupal\\migrate\\Plugin\\MigrateIdMapInterface', 'entity_field' => 'Drupal\\migrate\\Plugin\\MigrateEntityDestinationFieldInterface'); $plugin_interface = isset($plugin_interface_map[$type]) ? $plugin_interface_map[$type] : NULL; parent::__construct("Plugin/migrate/{$type}", $namespaces, $module_handler, $plugin_interface, $annotation); $this->alterInfo('migrate_' . $type . '_info'); $this->setCacheBackend($cache_backend, 'migrate_plugins_' . $type); }
/** * Constructs a LayoutPluginManager object. * * @param string $type * The plugin type, for example filter. * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations, * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { $plugin_definition_annotation_name = 'Drupal\\layout\\Annotation\\LayoutRegion'; parent::__construct("Plugin/LayoutRegion", $namespaces, $module_handler, $plugin_definition_annotation_name); $this->defaults += array('plugin_type' => 'LayoutRegion', 'register_theme' => TRUE); $this->setCacheBackend($cache_backend, 'layout_region'); $this->alterInfo('layout_region'); }
/** * @inheritdoc */ public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { $plugin_definition_annotation_name = 'Drupal\\geocoder\\Annotation\\GeocoderPlugin'; parent::__construct('Plugin/Geocoder/' . Container::camelize($type), $namespaces, $module_handler, 'Drupal\\geocoder\\Plugin\\GeocoderPluginInterface', $plugin_definition_annotation_name); $this->defaults += array('plugin_type' => strtolower($type)); $this->alterInfo('geocoder_plugins_' . $type); $this->setCacheBackend($cache_backend, 'geocoder:' . $type); }
/** * {@inheritdoc} */ public function processDefinition(&$definition, $plugin_id) { parent::processDefinition($definition, $plugin_id); // Ensure that every block has a category. if (empty($definition['category'])) { $definition['category'] = $this->getModuleName($definition['provider']); } }
/** * Constructs a ViewsPluginManager object. * * @param string $type * The plugin type, for example filter. * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations, * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * Cache backend instance to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. */ public function __construct($type, \Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { $plugin_definition_annotation_name = 'Drupal\\views\\Annotation\\Views' . Container::camelize($type); parent::__construct("Plugin/views/{$type}", $namespaces, $module_handler, 'Drupal\\views\\Plugin\\views\\ViewsPluginInterface', $plugin_definition_annotation_name); $this->defaults += array('parent' => 'parent', 'plugin_type' => $type, 'register_theme' => TRUE); $this->alterInfo('views_plugins_' . $type); $this->setCacheBackend($cache_backend, "views:{$type}"); }
/** * Constructs FruitPluginManager. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \DrupalCacheInterface $cache_backend * Cache backend instance to use. */ public function __construct(\Traversable $namespaces, \DrupalCacheInterface $cache_backend) { parent::__construct(FALSE, $namespaces); $this->discovery = new YamlDiscovery('fruits', Module::getDirectories()); $this->factory = new ContainerFactory($this); $this->alterInfo('fruit_plugin'); $this->setCacheBackend($cache_backend, 'fruit_plugins'); }
/** * {@inheritdoc} */ public function getDefinitions() { $definitions = parent::getDefinitions(); if (!\Drupal::moduleHandler()->moduleExists('imce') || !imce_access()) { unset($definitions['imce']); } return $definitions; }
/** * Constructs a new LanguageNegotiationMethodManager object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * An object that implements CacheBackendInterface * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * An object that implements ModuleHandlerInterface */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { parent::__construct('Plugin/LanguageNegotiation', $namespaces, $module_handler); $this->cacheBackend = $cache_backend; $this->cacheKeyPrefix = 'language_negotiation_plugins'; $this->cacheKey = 'language_negotiation_plugins'; $this->alterInfo('language_negotiation_info'); }
/** * Constructs a new FeaturesGenerationMethodManager object. * * @param \Traversable $namespaces * An object that implements \Traversable which contains the root paths * keyed by the corresponding namespace to look for plugin implementations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * An object that implements CacheBackendInterface. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * An object that implements ModuleHandlerInterface. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { parent::__construct('Plugin/FeaturesGeneration', $namespaces, $module_handler, 'Drupal\\features\\FeaturesGenerationMethodInterface'); $this->cacheBackend = $cache_backend; $this->cacheKeyPrefix = 'features_generation_methods'; $this->cacheKey = 'features_generation_methods'; $this->alterInfo('features_generation_info'); }
/** * {@inheritdoc} */ protected function findDefinitions() { $definitions = parent::findDefinitions(); if (isset($definitions['default'])) { // Always put default first. $definitions = ['default' => $definitions['default']] + $definitions; } return $definitions; }