alterInfo('ckeditor_plugin_info'); $this->setCacheBackend($cache_backend, 'ckeditor_plugins'); } /** * Retrieves enabled plugins' files, keyed by plugin ID. * * For CKEditor plugins that implement: * - CKEditorPluginButtonsInterface, not CKEditorPluginContextualInterface, * a plugin is enabled if at least one of its buttons is in the toolbar; * - CKEditorPluginContextualInterface, not CKEditorPluginButtonsInterface, * a plugin is enabled if its isEnabled() method returns TRUE * - both of these interfaces, a plugin is enabled if either is the case. * * Internal plugins (those that are part of the bundled build of CKEditor) are * excluded by default, since they are loaded implicitly. If you need to know * even implicitly loaded (i.e. internal) plugins, then set the optional * second parameter. * * @param \Drupal\editor\Entity\Editor $editor * A configured text editor object. * @param bool $include_internal_plugins * Defaults to FALSE. When set to TRUE, plugins whose isInternal() method * returns TRUE will also be included. * @return array * A list of the enabled CKEditor plugins, with the plugin IDs as keys and * the Drupal root-relative plugin files as values. * For internal plugins, the value is NULL. */ public function getEnabledPluginFiles(Editor $editor, $include_internal_plugins = FALSE) { $plugins = array_keys($this->getDefinitions()); $toolbar_buttons = $this->getEnabledButtons($editor); $enabled_plugins = []; $additional_plugins = []; foreach ($plugins as $plugin_id) { $plugin = $this->createInstance($plugin_id); if (!$include_internal_plugins && $plugin->isInternal()) { continue; } $enabled = FALSE; // Enable this plugin if it provides a button that has been enabled. if ($plugin instanceof CKEditorPluginButtonsInterface) { $plugin_buttons = array_keys($plugin->getButtons()); $enabled = (count(array_intersect($toolbar_buttons, $plugin_buttons)) > 0); } // Otherwise enable this plugin if it declares itself as enabled. if (!$enabled && $plugin instanceof CKEditorPluginContextualInterface) { $enabled = $plugin->isEnabled($editor); } if ($enabled) { $enabled_plugins[$plugin_id] = ($plugin->isInternal()) ? NULL : $plugin->getFile(); // Check if this plugin has dependencies that also need to be enabled. $additional_plugins = array_merge($additional_plugins, array_diff($plugin->getDependencies($editor), $additional_plugins)); } } // Add the list of dependent plugins. foreach ($additional_plugins as $plugin_id) { $plugin = $this->createInstance($plugin_id); $enabled_plugins[$plugin_id] = ($plugin->isInternal()) ? NULL : $plugin->getFile(); } // Always return plugins in the same order. asort($enabled_plugins); return $enabled_plugins; } /** * Gets the enabled toolbar buttons in the given text editor instance. * * @param \Drupal\editor\Entity\Editor $editor * A configured text editor object. * * @return string[] * A list of the toolbar buttons enabled in the given text editor instance. */ public static function getEnabledButtons(Editor $editor) { $toolbar_rows = []; $settings = $editor->getSettings(); foreach ($settings['toolbar']['rows'] as $row_number => $row) { $toolbar_rows[] = array_reduce($settings['toolbar']['rows'][$row_number], function (&$result, $button_group) { return array_merge($result, $button_group['items']); }, []); } return array_unique(NestedArray::mergeDeepArray($toolbar_rows)); } /** * Retrieves all available CKEditor buttons, keyed by plugin ID. * * @return array * All available CKEditor buttons, with plugin IDs as keys and button * metadata (as implemented by getButtons()) as values. * * @see \Drupal\ckeditor\CKEditorPluginButtonsInterface::getButtons() */ public function getButtons() { $plugins = array_keys($this->getDefinitions()); $buttons_plugins = []; foreach ($plugins as $plugin_id) { $plugin = $this->createInstance($plugin_id); if ($plugin instanceof CKEditorPluginButtonsInterface) { $buttons_plugins[$plugin_id] = $plugin->getButtons(); } } return $buttons_plugins; } /** * Injects the CKEditor plugins settings forms as a vertical tabs subform. * * @param array &$form * A reference to an associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param \Drupal\editor\Entity\Editor $editor * A configured text editor object. */ public function injectPluginSettingsForm(array &$form, FormStateInterface $form_state, Editor $editor) { $definitions = $this->getDefinitions(); foreach (array_keys($definitions) as $plugin_id) { $plugin = $this->createInstance($plugin_id); if ($plugin instanceof CKEditorPluginConfigurableInterface) { $plugin_settings_form = []; $form['plugins'][$plugin_id] = [ '#type' => 'details', '#title' => $definitions[$plugin_id]['label'], '#open' => TRUE, '#group' => 'editor][settings][plugin_settings', '#attributes' => [ 'data-ckeditor-plugin-id' => $plugin_id, ], ]; // Provide enough metadata for the drupal.ckeditor.admin library to // allow it to automatically show/hide the vertical tab containing the // settings for this plugin. Only do this if it's a CKEditor plugin that // just provides buttons, don't do this if it's a contextually enabled // CKEditor plugin. After all, in the latter case, we can't know when // its settings should be shown! if ($plugin instanceof CKEditorPluginButtonsInterface && !$plugin instanceof CKEditorPluginContextualInterface) { $form['plugins'][$plugin_id]['#attributes']['data-ckeditor-buttons'] = implode(' ', array_keys($plugin->getButtons())); } $form['plugins'][$plugin_id] += $plugin->settingsForm($plugin_settings_form, $form_state, $editor); } } } /** * Retrieves enabled plugins' iframe instance CSS files, keyed by plugin ID. * * @param \Drupal\editor\Entity\Editor $editor * A configured text editor object. * * @return string[] * Enabled plugins CKEditor CSS files, with plugin IDs as keys and CSS file * paths relative to the Drupal root (as implemented by getCssFiles()) as * values. * * @see \Drupal\ckeditor\CKEditorPluginCssInterface::getCssFiles() */ public function getCssFiles(Editor $editor) { $enabled_plugins = array_keys($this->getEnabledPluginFiles($editor, TRUE)); $css_files = []; foreach ($enabled_plugins as $plugin_id) { $plugin = $this->createInstance($plugin_id); if ($plugin instanceof CKEditorPluginCssInterface) { $css_files[$plugin_id] = $plugin->getCssFiles($editor); } } return $css_files; } }