Mercurial > hg > cmmr2012-drupal-site
diff core/modules/ckeditor/src/CKEditorPluginManager.php @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/ckeditor/src/CKEditorPluginManager.php Thu Jul 05 14:24:15 2018 +0000 @@ -0,0 +1,221 @@ +<?php + +namespace Drupal\ckeditor; + +use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Plugin\DefaultPluginManager; +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\editor\Entity\Editor; + +/** + * Provides a CKEditor Plugin plugin manager. + * + * @see \Drupal\ckeditor\CKEditorPluginInterface + * @see \Drupal\ckeditor\CKEditorPluginButtonsInterface + * @see \Drupal\ckeditor\CKEditorPluginContextualInterface + * @see \Drupal\ckeditor\CKEditorPluginConfigurableInterface + * @see \Drupal\ckeditor\CKEditorPluginCssInterface + * @see \Drupal\ckeditor\CKEditorPluginBase + * @see \Drupal\ckeditor\Annotation\CKEditorPlugin + * @see plugin_api + */ +class CKEditorPluginManager extends DefaultPluginManager { + + /** + * Constructs a CKEditorPluginManager 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) { + parent::__construct('Plugin/CKEditorPlugin', $namespaces, $module_handler, 'Drupal\ckeditor\CKEditorPluginInterface', 'Drupal\ckeditor\Annotation\CKEditorPlugin'); + $this->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; + } + +}