diff --git a/ckeditor.api.php b/ckeditor.api.php
index f5a12c5..b04c3ab 100644
--- a/ckeditor.api.php
+++ b/ckeditor.api.php
@@ -48,7 +48,7 @@ function hook_ckeditor_plugin() {
       'path' => drupal_get_path('module', 'my_module') . '/plugin_dir/',
       'buttons' => array(
         'button_name' => array(
-          'icon' => 'path to button icon',
+          'icon' => 'icon/plugin_name.png',
           'label' => 'Button Label',
         )
       )
@@ -57,6 +57,17 @@ function hook_ckeditor_plugin() {
 }
 
 /**
+ * Hook to extend/change CKEditor plugins.
+ *
+ * @param $plugins
+ *   An associative array of plugins.
+ */
+function hook_ckeditor_plugin_alter(&$plugins) {
+  // Remove a plugin button.
+  unset($plugins['plugin_name']['buttons']['button']);
+}
+
+/**
  * Hook to register the CKEditor security filter - it would appear in the security filters list on the profile setting page.
  */
 function hook_ckeditor_security_filter() {
@@ -84,5 +95,3 @@ function hook_ckeditor_settings_alter(&$settings) {
   // Change the ckeditor config path.
   $settings['customConfig'] = drupal_get_path('module', 'ckeditor') . '/ckeditor.config.js';
 }
-
-?>
diff --git a/ckeditor.ckeditor.inc b/ckeditor.ckeditor.inc
new file mode 100644
index 0000000..1ef529d
--- /dev/null
+++ b/ckeditor.ckeditor.inc
@@ -0,0 +1,169 @@
+<?php
+
+/**
+ * Implements hook_ckeditor_plugin().
+ */
+function ckeditor_ckeditor_plugin() {
+  $plugins = array();
+  $editor_path = ckeditor_path('local') . '/';
+  $plugin_dir = ckeditor_module_path('local') . '/plugins/';
+  $plugin_dir_additional = ckeditor_plugins_path('local') . '/';
+
+  /*
+   * External plugins
+   */
+  if (module_exists('ckeditor_swf') && file_exists(drupal_get_path('module', 'ckeditor_swf') . '/plugins/swf/plugin.js')) {
+    $plugins['ckeditor_swf'] = array(
+      'name' => 'swf',
+      'desc' => t('Support for the CKEditor SWF module'),
+      'path' => drupal_get_path('module', 'ckeditor_swf') . '/plugins/swf/',
+      'buttons' => FALSE,
+      'default' => 't',
+    );
+  }
+
+  if (module_exists('ckeditor_link') && file_exists(drupal_get_path('module', 'ckeditor_link') . '/plugins/link/plugin.js')) {
+    $plugins['ckeditor_link'] = array(
+      'name' => 'drupal_path',
+      'desc' => t('Support for the CKEditor Link module'),
+      'path' => drupal_get_path('module', 'ckeditor_link') . '/plugins/link/',
+      'buttons' => FALSE,
+      'default' => 't',
+    );
+  }
+
+  if (module_exists('linkit') && file_exists(drupal_get_path('module', 'linkit') . '/editors/ckeditor/plugin.js')) {
+    $plugins['linkit'] = array(
+      'name' => 'Linkit',
+      'desc' => t('Support for the Linkit module <em>(buttons: Linkit)</em>'),
+      'path' => drupal_get_path('module', 'linkit') . '/editors/ckeditor/',
+      'buttons' => array(
+        'Linkit' => array(
+          'label' => 'Linkit',
+          'icon' => 'linkit.png',
+        )
+      ),
+      'default' => 't',
+    );
+  }
+
+  /*
+   * CKEditor build-in plugins
+   */
+  $_editor_path = ltrim($editor_path, './');
+  if (file_exists($editor_path . 'plugins/tableresize/plugin.js')) {
+    $plugins['tableresize'] = array(
+      'name' => 'tableresize',
+      'desc' => t('Table Resize plugin'),
+      'path' => $_editor_path . 'plugins/tableresize/',
+      'buttons' => FALSE,
+      'default' => 't',
+    );
+  }
+
+  if (file_exists($editor_path . 'plugins/autogrow/plugin.js')) {
+    $plugins['autogrow'] = array(
+      'name' => 'autogrow',
+      'desc' => t('Auto Grow plugin'),
+      'path' => $_editor_path . 'plugins/autogrow/',
+      'buttons' => FALSE,
+      'default' => 'f',
+    );
+  }
+
+  if (file_exists($editor_path . 'plugins/stylesheetparser/plugin.js')) {
+    $plugins['stylesheetparser'] = array(
+      'name' => 'stylesheetparser',
+      'desc' => t('Stylesheet Parser plugin'),
+      'path' => $_editor_path . 'plugins/stylesheetparser/',
+      'buttons' => FALSE,
+      'default' => 'f',
+    );
+  }
+
+  /*
+   * CKEditor module plugins
+   */
+  $_plugin_dir = ltrim($plugin_dir, './');
+  if ($handle = opendir($plugin_dir)) {
+    while (FALSE !== ($file = readdir($handle))) {
+      if (is_dir($plugin_dir . $file) && file_exists($plugin_dir . $file . '/plugin.js')) {
+        $source = file_get_contents($plugin_dir . $file . '/plugin.js');
+        if (preg_match('#@file ([^\n\r]*)#', $source, $matches)) {
+          $plugins[$file] = array(
+            'name' => $file,
+            'desc' => t($matches[1]),
+            'path' => $_plugin_dir . $file . '/',
+            'buttons' => FALSE,
+            'default' => 'f',
+          );
+        }
+        else {
+          $plugins[$file] = array(
+            'name' => $file,
+            'desc' => t('Plugin file: @file', array('@file' => $file)),
+            'path' => $_plugin_dir . $file . '/',
+            'buttons' => FALSE,
+            'default' => 'f',
+          );
+        }
+      }
+    }
+    closedir($handle);
+  }
+
+  /*
+   * CKEditor module plugins - additional directory
+   */
+  $_plugin_dir_additional = ltrim($plugin_dir_additional, './');
+  if ($plugin_dir != $plugin_dir_additional && is_dir($plugin_dir_additional) && $handle = opendir($plugin_dir_additional)) {
+    while (FALSE !== ($file = readdir($handle))) {
+      if (is_dir($plugin_dir_additional . $file) && file_exists($plugin_dir_additional . $file . '/plugin.js')) {
+        $source = file_get_contents($plugin_dir_additional . $file . '/plugin.js');
+        if (preg_match('#@file ([^\n\r]*)#', $source, $matches)) {
+          $plugins[$file] = array(
+            'name' => $file,
+            'desc' => t($matches[1]),
+            'path' => $_plugin_dir_additional . $file . '/',
+            'buttons' => FALSE,
+            'default' => 'f',
+          );
+        }
+        else {
+          $plugins[$file] = array(
+            'name' => $file,
+            'desc' => t('Plugin file: ' . $file),
+            'path' => $_plugin_dir_additional . $file . '/',
+            'buttons' => FALSE,
+            'default' => 'f',
+          );
+        }
+      }
+    }
+
+    closedir($handle);
+  }
+
+  return $plugins;
+}
+
+/**
+ * Implements hook_ckeditor_plugin_alter().
+ */
+function ckeditor_ckeditor_plugin_alter(&$plugins) {
+  if (isset($plugins['media']) && module_exists('media') == FALSE) {
+    unset($plugins['media']);
+  }
+
+  if (isset($plugins['imce']) && module_exists('imce') == FALSE) {
+    unset($plugins['imce']);
+  }
+  // Remove page break button if there is no module to do this.
+  if (isset($plugins['drupalbreaks']['buttons']['DrupalPageBreak']) && !module_exists('paging') && !module_exists('pagebreak')) {
+    unset($plugins['drupalbreaks']['buttons']['DrupalPageBreak']);
+  }
+
+  if (isset($plugins['drupalbreaks'])) {
+    $plugins['drupalbreaks']['default'] = 't';
+  }
+}
diff --git a/ckeditor.module b/ckeditor.module
index 809b201..45d4a17 100644
--- a/ckeditor.module
+++ b/ckeditor.module
@@ -51,6 +51,21 @@ $_ckeditor_configuration = array();
 $_ckeditor_ids = array();
 
 /**
+ * Implements hook_hook_info().
+ */
+function ckeditor_hook_info() {
+  $hooks = array(
+    'ckeditor_plugin',
+    'ckeditor_plugin_alter',
+    'ckeditor_security_filter',
+    'ckeditor_security_filter_alter',
+    'ckeditor_settings_alter',
+  );
+
+  return array_fill_keys($hooks, array('group' => 'ckeditor'));
+}
+
+/**
  * Implementation of hook_menu().
  */
 function ckeditor_menu() {
diff --git a/includes/ckeditor.admin.inc b/includes/ckeditor.admin.inc
index 9a5a2fc..b4d0450 100644
--- a/includes/ckeditor.admin.inc
+++ b/includes/ckeditor.admin.inc
@@ -1743,7 +1743,7 @@ function ckeditor_toolbar_buttons_all() {
     '__group' => array('name' => FALSE, 'icon' => $path . '/images/buttons/group.png', 'title' => 'Group', 'row' => 4)
   );
 
-  $plugins = ckeditor_load_plugins(TRUE);
+  $plugins = ckeditor_load_plugins();
   foreach ($plugins as $plugin_name => $plugin) {
     if (!isset($plugin['buttons']) || $plugin['buttons'] == FALSE)
       continue;
diff --git a/includes/ckeditor.lib.inc b/includes/ckeditor.lib.inc
index a6f3ad5..e01a565 100644
--- a/includes/ckeditor.lib.inc
+++ b/includes/ckeditor.lib.inc
@@ -328,181 +328,20 @@ function ckeditor_scayt_langcode($lang) {
  *
  * @return array
  */
-function ckeditor_load_plugins($render = FALSE) {
-  $arr = array();
-  $base_path = '%base_path%';
-  $editor_path = '%editor_path%';
-  $ckeditor_path = '%module_path%';
-  $plugin_dir = '%plugin_dir%';
-  $plugin_dir_additional = '%plugin_dir_extra%';
-  $pattern = '#\.addButton\([\s]*[\'"](.*?)[\'"][\s]*\,[\s]*\{[\s]*(.*?)[\s]*\}#s';
-
-  /*
-   * External plugins
-   */
-  if (module_exists('ckeditor_swf') && file_exists(drupal_get_path('module', 'ckeditor_swf') . '/plugins/swf/plugin.js')) {
-    $arr['ckeditor_swf'] = array(
-      'name' => 'swf',
-      'desc' => t('Support for the CKEditor SWF module'),
-      'path' => $base_path . drupal_get_path('module', 'ckeditor_swf') . '/plugins/swf/',
-      'buttons' => FALSE,
-      'default' => 't'
-    );
-  }
-
-  if (module_exists('ckeditor_link') && file_exists(drupal_get_path('module', 'ckeditor_link') . '/plugins/link/plugin.js')) {
-    $arr['ckeditor_link'] = array(
-      'name' => 'drupal_path',
-      'desc' => t('Support for the CKEditor Link module'),
-      'path' => $base_path . drupal_get_path('module', 'ckeditor_link') . '/plugins/link/',
-      'buttons' => FALSE,
-      'default' => 't'
-    );
-  }
-
-  if (module_exists('linkit') && file_exists(drupal_get_path('module', 'linkit') . '/editors/ckeditor/plugin.js')) {
-    $arr['linkit'] = array(
-      'name' => 'Linkit',
-      'desc' => t('Support for the Linkit module <em>(buttons: Linkit)</em>'),
-      'path' => $base_path . drupal_get_path('module', 'linkit') . '/editors/ckeditor/',
-      'buttons' => array(
-        'Linkit' => array(
-          'title' => 'Linkit',
-          'icon' => $base_path . drupal_get_path('module', 'linkit') . '/editors/ckeditor/linkit.png'
-        )
-      ),
-      'default' => 't'
-    );
-  }
-
-  /*
-   * CKEditor build-in plugins
-   */
-  $_editor_path = ckeditor_path('local') . '/';
-  if (file_exists($_editor_path . 'plugins/tableresize/plugin.js')) {
-    $arr['tableresize'] = array(
-      'name' => 'tableresize',
-      'desc' => t('Table Resize plugin'),
-      'path' => $editor_path . 'plugins/tableresize/',
-      'buttons' => FALSE,
-      'default' => 't'
-    );
-  }
-
-  if (file_exists($_editor_path . 'plugins/autogrow/plugin.js')) {
-    $arr['autogrow'] = array(
-      'name' => 'autogrow',
-      'desc' => t('Auto Grow plugin'),
-      'path' => $editor_path . 'plugins/autogrow/',
-      'buttons' => FALSE,
-      'default' => 'f'
-    );
-  }
-
-  if (file_exists($_editor_path . 'plugins/stylesheetparser/plugin.js')) {
-    $arr['stylesheetparser'] = array(
-      'name' => 'stylesheetparser',
-      'desc' => t('Stylesheet Parser plugin'),
-      'path' => $editor_path . 'plugins/stylesheetparser/',
-      'buttons' => FALSE,
-      'default' => 'f'
-    );
-  }
-
-  /*
-   * CKEditor module plugins
-   */
-  $_plugin_dir = ckeditor_module_path('local') . '/plugins/';
-  if ($handle = opendir($_plugin_dir)) {
-    while (false !== ($file = readdir($handle))) {
-      if (is_dir($_plugin_dir . $file) && file_exists($_plugin_dir . $file . '/plugin.js')) {
-        $source = file_get_contents($_plugin_dir . $file . '/plugin.js');
-        $buttons = array();
-        if (preg_match_all($pattern, $source, $matches)) {
-          foreach ($matches[1] as $i => $button_name) {
-            if (preg_match('#(icon)[\s]*\:[\s]*([^\,\n]*)#', $matches[2][$i], $matches2)) {
-              $buttons[$button_name] = array();
-              $buttons[$button_name]['label'] = $button_name;
-              $matches2[2] = str_replace(array('this.path', '+', '\'', '"'), array('', '', '', ''), $matches2[2]);
-              $buttons[$button_name]['icon'] = trim($matches2[2]);
-            }
-          }
-        }
-        if (preg_match('#@file ([^\n\r]*)#', $source, $matches)) {
-          $arr[$file] = array(
-            'name' => $file,
-            'desc' => t($matches[1]),
-            'path' => $plugin_dir . $file . '/',
-            'buttons' => (count($buttons) > 0) ? $buttons : FALSE,
-            'default' => 'f'
-          );
-        }
-        else {
-          $arr[$file] = array(
-            'name' => $file,
-            'desc' => t('Plugin file: ' . $file),
-            'path' => $plugin_dir . $file . '/',
-            'buttons' => (count($buttons) > 0) ? $buttons : FALSE,
-            'default' => 'f'
-          );
-        }
-      }
-    }
-    closedir($handle);
-  }
-
-  /*
-   * CKEditor module plugins - additional directory
-   */
-  $_plugin_dir_additional = ckeditor_plugins_path('local') . '/';
-  if ($_plugin_dir != $_plugin_dir_additional && is_dir($_plugin_dir_additional) && $handle = opendir($_plugin_dir_additional)) {
-    while (false !== ($file = readdir($handle))) {
-      if (is_dir($_plugin_dir_additional . $file) && file_exists($_plugin_dir_additional . $file . '/plugin.js')) {
-        $source = file_get_contents($_plugin_dir_additional . $file . '/plugin.js');
-        $buttons = array();
-        if (preg_match_all($pattern, $source, $matches)) {
-          foreach ($matches[1] as $i => $button_name) {
-            if (preg_match('#(icon)[\s]*\:[\s]*([^\,\n]*)#', $matches[2][$i], $matches2)) {
-              $buttons[$button_name] = array();
-              $buttons[$button_name]['label'] = $button_name;
-              $matches2[2] = str_replace(array('this.path', '+', '\'', '"'), array('', '', '', ''), $matches2[2]);
-              $buttons[$button_name]['icon'] = trim($matches2[2]);
-            }
-          }
-        }
-        if (preg_match('#@file ([^\n\r]*)#', $source, $matches)) {
-          $arr[$file] = array(
-            'name' => $file,
-            'desc' => t($matches[1]),
-            'path' => $plugin_dir_additional . $file . '/',
-            'buttons' => (count($buttons) > 0) ? $buttons : FALSE,
-            'default' => 'f'
-          );
-        }
-        else {
-          $arr[$file] = array(
-            'name' => $file,
-            'desc' => t('Plugin file: ' . $file),
-            'path' => $plugin_dir_additional . $file . '/',
-            'buttons' => (count($buttons) > 0) ? $buttons : FALSE,
-            'default' => 'f'
-          );
-        }
-      }
-    }
-
-    closedir($handle);
-  }
+function ckeditor_load_plugins() {
+  $pattern = '#\.addButton\([\s]*[\'"](.*?)[\'"][\s]*\,[\s]*\{[\s]*((.|\s)*?)[\s]*\}#s';
 
   /*
    * CKEditor plugins registered by hook
    */
   $plugins = module_invoke_all('ckeditor_plugin');
 
+  drupal_alter('ckeditor_plugin', $plugins);
+
   foreach ($plugins as $i => $plugin) {
     if (file_exists($plugin['path'] . 'plugin.js')) {
       $source = file_get_contents($plugin['path'] . 'plugin.js');
-      $plugins[$i]['path'] = $base_path . $plugin['path'];
+      $plugins[$i]['path'] = ckeditor_base_path('relative') . '/' . $plugin['path'];
       if (!isset($plugin['buttons']) || count($plugin['buttons']) == 0) {
         $buttons = array();
         if (preg_match_all($pattern, $source, $matches)) {
@@ -522,29 +361,10 @@ function ckeditor_load_plugins($render = FALSE) {
       unset($plugins[$i]);
     }
   }
-  $arr = array_merge($arr, $plugins);
-
-  if (isset($arr['media']) && module_exists('media') == FALSE) {
-    unset($arr['media']);
-  }
 
-  if (isset($arr['imce']) && module_exists('imce') == FALSE) {
-    unset($arr['imce']);
-  }
-  //remove page break button if there is no module to do this
-  if (isset($arr['drupalbreaks']['buttons']['DrupalPageBreak']) && !module_exists('paging') && !module_exists('pagebreak')) {
-    unset($arr['drupalbreaks']['buttons']['DrupalPageBreak']);
-  }
-
-  if (isset($arr['drupalbreaks'])) {
-    $arr['drupalbreaks']['default'] = 't';
-  }
+  ksort($plugins);
 
-  ksort($arr);
-  if ($render === TRUE) {
-    $arr = ckeditor_plugins_render($arr);
-  }
-  return $arr;
+  return $plugins;
 }
 
 /**
@@ -558,11 +378,11 @@ function ckeditor_plugins_render($plugins) {
   $render["%plugin_dir%"] = $render["%module_path%"] . 'plugins/';
   $render["%plugin_dir_extra%"] = ckeditor_plugins_path('relative') . '/';
 
-  foreach ((array) $plugins as $i => $plugin) {
-    $plugins[$i]['path'] = str_replace(array_keys($render), array_values($render), $plugin['path']);
-  }
+ foreach ((array) $plugins as $i => $plugin) {
+   $plugins[$i]['path'] = str_replace(array_keys($render), array_values($render), $plugin['path']);
+ }
 
-  return $plugins;
+ return $plugins;
 }
 
 /**
@@ -820,15 +640,23 @@ function ckeditor_profile_settings_compile($global_profile, $profile) {
     $settings['loadPlugins'] = ckeditor_plugins_render($conf['loadPlugins']);
 
     if (array_key_exists('media', $settings['loadPlugins']) && module_exists('media')) {
-      module_load_include('inc', 'media', 'includes/media.browser');
-      $javascript = media_browser_js();
-      foreach ($javascript as $key => $definitions) {
-        foreach ($definitions as $definition) {
-          $function = 'drupal_add_' . $key;
-          call_user_func_array($function, $definition);
+      if (module_exists('media_wysiwyg')) {
+        media_wysiwyg_include_browser_js();
+
+        drupal_add_js(drupal_get_path('module', 'media_wysiwyg') . '/js/media_wysiwyg.filter.js');
+        drupal_add_js(drupal_get_path('module', 'media_wysiwyg') . '/wysiwyg_plugins/media_ckeditor/library.js', array('scope' => 'footer', 'weight' => -20));
+      }
+      else {
+        module_load_include('inc', 'media', 'includes/media.browser');
+        $javascript = media_browser_js();
+        foreach ($javascript as $key => $definitions) {
+          foreach ($definitions as $definition) {
+            $function = 'drupal_add_' . $key;
+            call_user_func_array($function, $definition);
+          }
         }
+        drupal_add_js(drupal_get_path('module', 'ckeditor') . '/plugins/media/library.js', array('scope' => 'footer', 'weight' => -20));
       }
-      drupal_add_js(drupal_get_path('module', 'ckeditor') . '/plugins/media/library.js', array('scope' => 'footer', 'weight' => -20));
     }
   }
   else {
