Answers.Body: <p>I found the solution on my own. It's actually as simple as writing three lines of code.</p>
  
  <p>First of all I</p>
  
  <ol>
  <li>removed the assetbundle class (<code>RedactorBundle</code>)</li>
  <li>moved my <code>redactorplugin.js</code> to another directory (to <code>myplugin/src/resources</code>)<br>
  …which is not really necessary, but since I don't need the assetbundle any longer I wanted to flatten the directory structure</li>
  </ol>
  
  <p>Then I just added this hook to my plugin class' <code>init()</code> method.</p>
  
  <pre class="lang-php prettyprint-override"><code>
  //  register new plugin source for Redactor using one of Redactor's events
  Event::on(Field::class, Field::EVENT_REGISTER_PLUGIN_PATHS, function (RegisterPluginPathsEvent $event) {
      $event-&gt;paths[] = Craft::getAlias('@myplugin/resources/');
  });
  </code></pre>
  
  <p>And that's it. Why didn't I came up to this a bit earlier…? However, this is the way to go.</p>
  
  <p>In the end I only have these files left:</p>
  
  <pre><code>myplugin/
  ├── README.md
  ├── composer.json
  └── src
      ├── MyPlugin.php
      ├── resources
      │   └── redactorplugin.js
      └── icon.svg
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-10-25T09:08:50.200Z
Answers.LastActivityDate: 2019-10-25T09:08:50.200Z
Answers.UserDisplayName: Arvid
Body: <h2>TL;DR</h2>
  
  <p><strong>What is the correct/recommended way to implement a Redactor plugin within a Craft plugin?</strong></p>
  
  <h2>My intention</h2>
  
  <p>I'd like to implement a Craft CMS 3 plugin that adds a new Reactor plugin.</p>
  
  <p>Normally (when not implementing Craft plugins) I'd just add my Redactor plugin file, let's say <code>redactorplugin.js</code> to <code>./config/redactor/plugins/redactorplugin.js</code> (while <code>./</code> is the project's root directory).</p>
  
  <p>But for the sake of reusability I'd like to build a Craft plugin instead of manually putting the <code>redactorplugin.js</code> file to the Redactor plugin directory of each project.</p>
  
  <h2>My problem</h2>
  
  <p>I get an error because my Redactor plugin doesn't seem to be loaded correctly or maybe it's loaded in a wrong order (like too late for Redactor or something) or it's just not properly initialized.</p>
  
  <p>Long story short, I get this error message:<br>
  <code>Redactor plugin not found: &lt;handle&gt;</code></p>
  
  <h2>My current attempt</h2>
  
  <p>My Craft plugin which I am building has the following file structure (to be honest, I spared a few files, but they aren't important for now):</p>
  
  <pre><code>myplugin/
  ├── README.md
  ├── composer.json
  └── src
      ├── MyPlugin.php
      ├── assetbundles
      │   └── redactor
      │       ├── RedactorBundle.php
      │       └── dist
      │           └── redactorplugin.js
      └── icon.svg
  </code></pre>
  
  <p>So, basically I have the Redactor plugin file <code>redactorplugin.js</code> and an assetbundle implementation which is the PHP class <code>RedactorBundle</code>.</p>
  
  <p>The latter one looks as follows:</p>
  
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  
  namespace myplugin\assetbundles\redactor;
  
  use craft\redactor\assets\field\FieldAsset;
  use craft\web\AssetBundle;
  
  class RedactorBundle extends AssetBundle
  {
  
      public function init()
      {
          $this-&gt;sourcePath = "@myplugin/assetbundles/redactor/dist";
  
          $this-&gt;depends = [
              FieldAsset::class,
          ];
  
          $this-&gt;js = [
              'redactorplugin.js',
          ];
  
          parent::init();
      }
  }
  </code></pre>
  
  <p>What happens here so far, is that my assetbundle <code>RedactorBundle</code> is being loaded after loading the <code>craft\redactor\assets\field\FieldAsset</code> assetbundle, which happens for example when I head to an entry's edit page in the Control Panel of Craft.</p>
  
  <p>While observing the network traffic in my browser dev-tools I can then see that <code>redactorplugin.js</code> is loaded right after some Redactor related JS files (after <code>RedactorInput.min.js</code> and <code>RedactorOverrides.min.js</code>, but before <code>EntryTypeSwitcher.min.js</code> if that even matters).</p>
  
  <p>By the way, this is the <code>redactorplugin.js</code> file's content:</p>
  
  <pre class="lang-js prettyprint-override"><code>(function ($R) {
      $R.add('plugin', 'redactorplugin', {
          init: function (app) {
              console.log('init');
          },
          start: function () {
              console.log('start');
          },
      });
  })(Redactor);
  console.log(Redactor); //  will be logged as $R
  </code></pre>
  
  <p>In the Console tab of my browser's dev-tools I can see that <code>$R</code> is being logged (<code>init</code> and <code>start</code> aren't logged though, because I still need to add the plugin to my Redactor config). When expanding <code>$R</code> I can see a lot of stuff including the list of Redactor plugins where my <code>redactorplugin</code> is also listed.</p>
  
  <p>So, apparently this already works.</p>
  
  <h2>But …</h2>
  
  <p>After adding <code>redactorplugin</code> to my Redactor config (e.g. in <code>./config/redactor/Simple.json</code>) I get the above mentioned error.</p>
  
  <p><code>Invalid Configuration – yii\base\InvalidConfigException</code><br>
  with the message:<br>
  <code>Redactor plugin not found: redactorplugin</code></p>
  
  <p>There seems to be going on some naming convention stuff. Craft/Redactor tries to load the <code>redactorplugin.js</code> on its own although it has already been loaded using the assetbundle.</p>
  
  <h2>Solution? – Nah…</h2>
  
  <p>When I just create an empty file called <code>redactorplugin.js</code> (literally empty, no single line of code) and put it in the <code>./config/redactor/plugins/</code> directory then everything works fine! Woohoo!<br>
  (Which is because two files of name <code>redactorplugin.js</code> will be loaded, the empty dummy file and the one inserted by the assetbundle.)</p>
  
  <p>So, I would conclude that a solution (or at least a workaround) could be to create such a dummy file on installation of my Craft plugin.</p>
  
  <p>Like:</p>
  
  <pre class="lang-php prettyprint-override"><code>namespace myplugin\assetbundles\redactor;
  
  use craft\base\Plugin;
  
  class MyPlugin extends Plugin
  {
      // … init() and other methods here …
  
      protected function afterInstall()
      {
          //  TODO: create dummy file for Redactor plugin
      }
  
      protected function beforeUninstall(): bool
      {
          //  TODO: remove dummy file from ./config/redactor/plugins/
  
          return true;
      }
  }
  </code></pre>
  
  <p>Unfortunately, this seems to be clumsy to me. First of all, creating dummy files to make something work feels really strange. Also, creating those files will result in "unknown files" in Git. This whole thing doesn't feel right.</p>
  
  <h2>Is using assetbundles the correct way at all?</h2>
  
  <p>Is there any other way?</p>
  
  <p>What is the actually recommended way to achieve my goal? (Which is adding Redactor plugins from within a Craft plugin.)</p>
  
Tags: <plugin-development><craft3><redactor>
Title: "Redactor plugin not found" – How to properly implement Craft plugins providing Redactor plugins?
ThreadText: # "Redactor plugin not found" – How to properly implement Craft plugins providing Redactor plugins?
  
  (Asked by: username_0 on 2019-10-24)
  
  ## TL;DR
  
  **What is the correct/recommended way to implement a Redactor plugin within a Craft plugin?**
  
  ## My intention
  
  I'd like to implement a Craft CMS 3 plugin that adds a new Reactor plugin.
  
  Normally (when not implementing Craft plugins) I'd just add my Redactor plugin file, let's say `redactorplugin.js` to `./config/redactor/plugins/redactorplugin.js` (while `./` is the project's root directory).
  
  But for the sake of reusability I'd like to build a Craft plugin instead of manually putting the `redactorplugin.js` file to the Redactor plugin directory of each project.
  
  ## My problem
  
  I get an error because my Redactor plugin doesn't seem to be loaded correctly or maybe it's loaded in a wrong order (like too late for Redactor or something) or it's just not properly initialized.
  
  Long story short, I get this error message:  
  `Redactor plugin not found: <handle>`
  
  ## My current attempt
  
  My Craft plugin which I am building has the following file structure (to be honest, I spared a few files, but they aren't important for now):
  
  ```
  myplugin/
  ├── README.md
  ├── composer.json
  └── src
      ├── MyPlugin.php
      ├── assetbundles
      │   └── redactor
      │       ├── RedactorBundle.php
      │       └── dist
      │           └── redactorplugin.js
      └── icon.svg
  
  ```
  
  So, basically I have the Redactor plugin file `redactorplugin.js` and an assetbundle implementation which is the PHP class `RedactorBundle`.
  
  The latter one looks as follows:
  
  ```php
  <?php
  
  namespace myplugin\assetbundles\redactor;
  
  use craft\redactor\assets\field\FieldAsset;
  use craft\web\AssetBundle;
  
  class RedactorBundle extends AssetBundle
  {
  
      public function init()
      {
          $this->sourcePath = "@myplugin/assetbundles/redactor/dist";
  
          $this->depends = [
              FieldAsset::class,
          ];
  
          $this->js = [
              'redactorplugin.js',
          ];
  
          parent::init();
      }
  }
  
  ```
  
  What happens here so far, is that my assetbundle `RedactorBundle` is being loaded after loading the `craft\redactor\assets\field\FieldAsset` assetbundle, which happens for example when I head to an entry's edit page in the Control Panel of Craft.
  
  While observing the network traffic in my browser dev-tools I can then see that `redactorplugin.js` is loaded right after some Redactor related JS files (after `RedactorInput.min.js` and `RedactorOverrides.min.js`, but before `EntryTypeSwitcher.min.js` if that even matters).
  
  By the way, this is the `redactorplugin.js` file's content:
  
  ```js
  (function ($R) {
      $R.add('plugin', 'redactorplugin', {
          init: function (app) {
              console.log('init');
          },
          start: function () {
              console.log('start');
          },
      });
  })(Redactor);
  console.log(Redactor); //  will be logged as $R
  
  ```
  
  In the Console tab of my browser's dev-tools I can see that `$R` is being logged (`init` and `start` aren't logged though, because I still need to add the plugin to my Redactor config). When expanding `$R` I can see a lot of stuff including the list of Redactor plugins where my `redactorplugin` is also listed.
  
  So, apparently this already works.
  
  ## But …
  
  After adding `redactorplugin` to my Redactor config (e.g. in `./config/redactor/Simple.json`) I get the above mentioned error.
  
  `Invalid Configuration – yii\base\InvalidConfigException`  
  with the message:  
  `Redactor plugin not found: redactorplugin`
  
  There seems to be going on some naming convention stuff. Craft/Redactor tries to load the `redactorplugin.js` on its own although it has already been loaded using the assetbundle.
  
  ## Solution? – Nah…
  
  When I just create an empty file called `redactorplugin.js` (literally empty, no single line of code) and put it in the `./config/redactor/plugins/` directory then everything works fine! Woohoo!  
  (Which is because two files of name `redactorplugin.js` will be loaded, the empty dummy file and the one inserted by the assetbundle.)
  
  So, I would conclude that a solution (or at least a workaround) could be to create such a dummy file on installation of my Craft plugin.
  
  Like:
  
  ```php
  namespace myplugin\assetbundles\redactor;
  
  use craft\base\Plugin;
  
  class MyPlugin extends Plugin
  {
      // … init() and other methods here …
  
      protected function afterInstall()
      {
          //  TODO: create dummy file for Redactor plugin
      }
  
      protected function beforeUninstall(): bool
      {
          //  TODO: remove dummy file from ./config/redactor/plugins/
  
          return true;
      }
  }
  
  ```
  
  Unfortunately, this seems to be clumsy to me. First of all, creating dummy files to make something work feels really strange. Also, creating those files will result in "unknown files" in Git. This whole thing doesn't feel right.
  
  ## Is using assetbundles the correct way at all?
  
  Is there any other way?
  
  What is the actually recommended way to achieve my goal? (Which is adding Redactor plugins from within a Craft plugin.)
  
  **Tags:** plugin-development, craft3, redactor
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2019-10-25. Score: 1 | Accepted answer
  
  I found the solution on my own. It's actually as simple as writing three lines of code.
  
  First of all I
  
  1. removed the assetbundle class (`RedactorBundle`)
  2. moved my `redactorplugin.js` to another directory (to `myplugin/src/resources`)  
     …which is not really necessary, but since I don't need the assetbundle any longer I wanted to flatten the directory structure
  
  Then I just added this hook to my plugin class' `init()` method.
  
  ```php
  
  //  register new plugin source for Redactor using one of Redactor's events
  Event::on(Field::class, Field::EVENT_REGISTER_PLUGIN_PATHS, function (RegisterPluginPathsEvent $event) {
      $event->paths[] = Craft::getAlias('@myplugin/resources/');
  });
  
  ```
  
  And that's it. Why didn't I came up to this a bit earlier…? However, this is the way to go.
  
  In the end I only have these files left:
  
  ```
  myplugin/
  ├── README.md
  ├── composer.json
  └── src
      ├── MyPlugin.php
      ├── resources
      │   └── redactorplugin.js
      └── icon.svg
  
  ```
  
  
  ---
  
  