By: Prafull Ranjan
March 5 2018

Creating a custom CKEditor plugin in Drupal 8

The editing process can turn hectic involving rigorous and meticulous search, editing, categorization, and lot other modifications. In his article ‘How to De-couple Drupal in 2018’, Dries talks about creating and conceiving a custom editorial interfaces that helps give content editors the control they need over a growing number of channels. 

Therefore, in this tutorial, we are going to develop a custom CKEditor module for your Drupal website through a plugin to extend the functionalities of CKEditor. 

As an example, we are going to develop the Google search module, here.

What is CKEditor?
The content for the web is created in HTML and incorporates both text and special tags. These tags are utilized to mark-up content elements keeping their basic components in mind. They are defined as “headings”, “paragraphs”, “bold text”, “italics” etc. CKEditor only conceals the HTML tags from the web user and presents it in the graphical user interface. It is also a WYSIWYG rich editor which implies that the written input is equivalent to the result output.

CKEditor in Drupal

Even though CKEditor is part of Drupal 8’ core (an out-of-the-box feature), there are certain features and functionalities which need to be added through plugins. Likewise, the search functionality will be added to improve the interface for the editor. The module also provides extended APIs to widen its features by means of creating custom modules.  

CKEditor Plugin 

The CKEditor plugin will assist in adding features to the existing ecosystem. This will support and enable customization.

Functions: 

  1. CKEditorPluginInterface::getConfig : Returns the additions to CKEDITOR.config for a specific CKEditor instance.
  2. CKEditorPluginInterface::getDependencies : Returns a list of plugins this plugin requires.
  3. CKEditorPluginInterface::getFile : Returns the Drupal root-relative file path to the plugin JavaScript file.
  4. CKEditorPluginInterface::getLibraries : Returns a list of libraries this plugin requires.
  5. CKEditorPluginInterface::isInternal : Indicates if this plugin is part of the optimized CKEditor build.
  6. PluginInspectionInterface::getPluginDefinition : Gets the definition of the plugin implementation.
  7. PluginInspectionInterface::getPluginId : Gets the plugin_id of the plugin instance.

Now we’ll create a custom Drupal 8 CKEditor Google Search module which will provide a search button with the functionality of Google search the selected words in the editor using the Google Search plugin

Let’s begin!!

Steps for developing the module

Step 1: Create a basic structure of files and folders which are needed to develop Drupal 8 CKEditor custom module.

Creating a basic structure of files and folders

Step 2: Define the ckeditor_googlesearch.info.yml file to make your Drupal site aware of your module.

name: CKEditor Google Search
type: module
description: This plugin module adds the google search feature to CKEditor in Drupal 8
package: CKEditor
dependencies:
  - ckeditor
version: '8.x-1.0'
core: '8.x'
project: 'ckeditor_googlesearch'

Step 3: Now let’s create the plugin file. In this case, you can define it as Search.php

<?php

namespace Drupal\ckeditor_googlesearch\Plugin\CKEditorPlugin;

use Drupal\ckeditor\CKEditorPluginBase;
use Drupal\editor\Entity\Editor;

/**
 * Defines the "Google Search" plugin.
 *
 * @CKEditorPlugin(
 *   id = "googlesearch",
 *   label = @Translation("Google Search"),
 *   module = "ckeditor_googlesearch"
 * )
 */
class Search extends CKEditorPluginBase {

  /**
   * {@inheritdoc}
   */
  public function getFile() {
    if ($library_path = libraries_get_path('googlesearch')) {
      return $library_path . '/plugin.js';
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getDependencies(Editor $editor) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getLibraries(Editor $editor) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function isInternal() {
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function getButtons() {
    return [
      'googlesearch' => [
        'label' => t('Google Search'),
        'image' => libraries_get_path('googlesearch') . '/icons/googlesearch.png',
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function isEnabled(Editor $editor) {
  }

  /**
   * {@inheritdoc}
   */
  public function getConfig(Editor $editor) {
    return [];
  }

}

Here the Search class has extended CKEditorPluginBase and as we are using the plugin from official CKEditor website. It needs to be downloaded and saved in your /libraries folder of Drupal site. In case there’s no libraries folder in your Drupal site directory, create one in the same directory which has your modules & themes folders.

The structure will be like: [D8-root]/libraries/googlesearch/ (as the Google Search plugin will have the root folder name as “googlesearch”)

After getting the Drupal 8 CKeditor plugins, go to the Search.php file, we need to add documentation about our plugin so that Drupal is aware of the plugin. You can include it by copying the code :

/**
 * Defines the "Google Search" plugin.
 *
 * @CKEditorPlugin(
 *   id = "googlesearch",
 *   label = @Translation("Google Search"),
 *   module = "ckeditor_googlesearch"
 * )
 */
  • id: Plugin’s root folder name (in our case, it’s “googlesearch”).
  • label: Plugin’s official name (in our case, it’s “Google Search”).
  • Module: Your module’s machine name (in our case, it’s ckeditor_googlesearch).

This time, we need to inform Drupal about the storage of our plugin files. For this we have to override the function getFile() as : 
 

public function getFile() {
    if ($library_path = libraries_get_path('googlesearch')) {
      return $library_path . '/plugin.js';
    }
  }


libraries_get_path() function will return the path of the specified library (in our case, it’s “googlesearch”) or will return FALSE if it isn’t available.

Now, as we need a button for this Google Search feature in our text editor, so we need to override the function getButtons() as: 

public function getButtons() {
    return [
      'googlesearch' => [
        'label' => t('Google Search'),
        'image' => libraries_get_path('googlesearch') . '/icons/googlesearch.png',
      ],
    ];
  }

In this function, we have to create an array “googlesearch” with the following properties:

  • label: to give the icon a label.
  • Image: Path to the search icon file of the plugin.

Step 4: Now, we will create ckeditor_googlesearch.install file

<?php

/**
 * @file
 * Check requirements for the CKEditor Google Search module.
 */

/**
 * Implements hook_requirements().
 */
function ckeditor_googlesearch_requirements($phase) {
  $requirements = [];

  if ($phase == 'install' || $phase == 'runtime') {
    $plugin_detected = file_exists(DRUPAL_ROOT . '/libraries/googlesearch/plugin.js');

    if ($plugin_detected) {
      $requirements['googlesearch'] = [
        'title' => t('CKEditor Google Search'),
        'value' => t('Plugin detected'),
        'severity' => REQUIREMENT_OK,
      ];
    }
    else {
      $requirements['googlesearch'] = [
        'title' => t('CKEditor Google Search'),
        'value' => t('Plugin not detected'),
        'severity' => REQUIREMENT_ERROR,
        'description' => t('Before you can use the CKEditor Google Search module, you need to download the googlesearch plugin from ckeditor.com and place it in /libraries/googlesearch. Check the README.txt for more information. <a href=":plugin_url">Get the plugin here</a>.', [':plugin_url' => 'https://ckeditor.com/cke4/addon/googlesearch']),
      ];
    }
  }

  return $requirements;
}

Here we’ll implement hook_requirements() to check if the plugin folder “googlesearch” is copied in the libraries folder or not. If the plugin folder is available then only the module will be installed or else it’ll generate an error which will ask for placing the plugin files in the required directory, as shown below :

Error message asking for placing the plugin files in the required directory

This implementation will help in avoiding site crash while configuring the module without placing the plugin files.

Step 5:  In the ckeditor_googlesearch.module file we’ll implement hook_help() to provide a help page regarding the installation instruction and usage of the module.

<?php

/**
 * @file
 * Contains ckeditor_googlesearch.module.
 */

use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Implements hook_help().
 */
function ckeditor_googlesearch_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.ckeditor_googlesearch':
      $output = '';
      $output .= '<h3>' . t('Ckeditor Google Search') . '</h3>';
      $output .= '<p>' . t('The module adds a Google Search button to the editor toolbar.') . '</p>';
      $output .= '<h3>' . t('Uses') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('Settings') . '</dt>';
      $output .= '<dd>' . t('In the <a href=":text-formats">text formats</a> that use ckeditor, move the Google Search icon into the active toolbar.', [':text-formats' => \Drupal::url('filter.admin_overview')]) . '</dd>';
      $output .= '</dl>';
      return $output;

    default:
  }
}

Installation & Configuration of module

Step 1: On successful creation of the module, it’s time to enable it. To enable the module go to the link : [D8-site]/admin/modules, search for the CKEditor Google Search module and enable the module as shown below and click install.

Enabling the CKEditor Google Search module

Step 2: After installing the module, go the configuration link: [D8-site]/admin/config/content/formats and select any of the text formats where you want to place the tool. 

We’ll be configuring it for Basic HTML by visiting the link: [D8-site]/admin/config/content/formats/manage/basic_html.

In the Toolbar Configuration, you’ll find the icon as present in the plugin’s icon folder.

Finding the icon in the toolbar configuration

Step 3: Now drag and drop this icon into the Active toolbar pane to use this tool in your editor as shown below :

placing the icon on the Active toolbar section

and it’ll be available in Active toolbar pane as shown below. Click ‘Save Configuration’ to save the configuration

Icon added in the 'active toolbar'

Usage Of The Module

  1. Now go to the link where you’ll use this editor. As you use your text editor, you can see the tool icon in the toolbar. 
     Adding content in the text editor; module icon highlighted with red
  2. Select the words and click on the Google Search button. A new page will open in the browser Google presenting the search results of the selected words as shown below :
Selecting and searching the words and clicking on the Google Search button; search result for the selected words


Congratulation! 

You’ve successfully created the module extending the functionality of CKEditor. 

In case of an issue, you can contribute to the module here. And in case of any doubt, you can comment below.