Jump to:
| Project: | Drupal core |
| Version: | 8.x-dev |
| Component: | plugin system |
| Category: | support request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | active |
| Issue tags: | DX |
Issue Summary
Here's a tale of woe and tears. :)
So in Spark, there's some code to set up CKEditor:
// Enable CKEditor for both Filtered and Full HTML. For now, without any
// custom configuration.
$editor = entity_create('editor', array(
'format' => 'filtered_html',
'editor' => 'ckeditor',
'settings' => array(
'toolbar' => array(
'buttons' => array(
array(
'Bold', 'Italic', '|',
'NumberedList', 'BulletedList', 'Blockquote', '|',
'JustifyLeft', 'JustifyCenter', 'JustifyRight', '|',
'Link', 'Unlink',
),
),
'format_list' => array('p'),
'style_list' => array(),
),
),
));
$editor->save();
$editor = entity_create('editor', array(
'format' => 'full_html',
'editor' => 'ckeditor',
'settings' => array(
'toolbar' => array(
'buttons' => array(
array(
'Source', '|', 'Bold', 'Italic', '|',
'NumberedList', 'BulletedList', 'Blockquote', '|',
'JustifyLeft', 'JustifyCenter', 'JustifyRight', '|',
'Link', 'Unlink', '|', 'Image', 'Maximize',
),
),
'format_list' => array('p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'),
'style_list' => array(),
),
),
));
$editor->save();When this code runs, I get:
Drupal\Component\Plugin\Exception\PluginException: The plugin (ckeditor) did not specify an instance class. in Drupal\Component\Plugin\Factory\DefaultFactory::getPluginClass() (line 62 of /Users/webchick/Sites/spark/spork/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php).I have absolutely no idea what any of those words even mean.
But, it gave me a line number and a file name, so I started debugging there.
public static function getPluginClass($plugin_id, DiscoveryInterface $discovery) {
$plugin_definition = $discovery->getDefinition($plugin_id);
if (empty($plugin_definition['class'])) {
throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $plugin_id)); # <-- THIS IS LINE 62
}
$class = $plugin_definition['class'];
…Ok, so this is happening because $discovery->getDefinition($plugin_id); didn't return what was expected; $plugin_definition['class'] is coming back empty.
What is in $plugin_definition, then?
public static function getPluginClass($plugin_id, DiscoveryInterface $discovery) {
$plugin_definition = $discovery->getDefinition($plugin_id);
if ($plugin_id == 'ckeditor') { var_dump($plugin_definition); } # <-- DEBUGGINGThat gives me NULL. Well, that's obviously ungood.
So what's $discovery, then?
if ($plugin_id == 'ckeditor') { echo '<pre>' . print_r($discovery, 1) . '</pre>'; }
Drupal\Core\Plugin\Discovery\CacheDecorator Object
(
[cacheKey:protected] => editor
[cacheBin:protected] => cache
[cacheExpire:protected] => 0
[cacheTags:protected] => Array
(
)
[definitions:protected] => Array
(
)
[decorated:protected] => Drupal\Core\Plugin\Discovery\AlterDecorator Object
(
[hook:protected] => editor_info
[decorated:protected] => Drupal\Component\Plugin\Discovery\ProcessDecorator Object
(
[decorated:protected] => Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery Object
(
[pluginNamespaces:protected] => Array
(
)
[annotationNamespaces:protected] => Array
(
[Drupal\Component\Annotation] => /Users/webchick/Sites/spark/spork/core/lib
[Drupal\Core\Annotation] => /Users/webchick/Sites/spark/spork/core/lib
)
[pluginDefinitionAnnotationName:protected] => Drupal\Core\Annotation\Plugin
[owner] => editor
[type] => editor
[rootNamespaces] =>
)
[processCallback:protected] => Array
(
[0] => Drupal\editor\Plugin\EditorManager Object
(
[discovery:protected] => Drupal\Core\Plugin\Discovery\CacheDecorator Object
*RECURSION*
[factory:protected] => Drupal\Component\Plugin\Factory\DefaultFactory Object
(
[discovery:protected] => Drupal\Core\Plugin\Discovery\CacheDecorator Object
*RECURSION*
)
[mapper:protected] =>
[defaults:protected] => Array
(
)
)
[1] => processDefinition
)
)
)
)(side note: var_export() doesn't work here because you get a fatal error about too many nested levels of recursion.)
Well. Now what? So this is a Drupal\Core\Plugin\Discovery\CacheDecorator object? Where do I find that?
(Note: I know that it's in core/lib/Drupal/Core/Plugin/Discovery/, but I'm not sure that a normal person would to look under there.)
I go into CacheDecorator.php, under public function getDefinition($plugin_id) { and added more debugging.
public function getDefinition($plugin_id) {
if ($plugin_id == 'ckeditor') { var_dump($this->definitions); } # <-- DEBUGGING
// Optimize for fast access to definitions if they are already in memory.
if (isset($this->definitions)) {
// Avoid using a ternary that would create a copy of the array.
if (isset($this->definitions[$plugin_id])) {
return $this->definitions[$plugin_id];
}
else {
return;
}
}
if ($plugin_id == 'ckeditor') { var_dump('banana'); } # <-- MORE DEBUGGINGIt just returns because $this->definitions is an empty array; banana never gets printed.
And now... Ok, so… uh… seriously, now what? :(
Comments
#1
chx said this probably had something to do with EntityManager. No reference whatsoever to EntityManager in any of the error messages. I thought it might be in the callstack so I tried putting a:
var_dump(debug_backtrace());Now I get a WSOD. :P error_log says:
Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 264243201 bytes) in /Users/webchick/Sites/spark/spork/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php on line 60[Thu Jan 24 01:05:19 2013] [error] [client 127.0.0.1] Uncaught PHP Exception Drupal\\Component\\Plugin\\Exception\\PluginException: "The plugin (ckeditor) did not specify an instance class." at /Users/webchick/Sites/spark/spork/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php line 63
chx says I can call debug_backtrace() with DEBUG_BACKTRACE_IGNORE_ARGS to stop that from happening, but I've never had to use that parameter before. He also said I can use print_r() but that's annoying because xdebug doesn't nicely format calls to print_r(). (Also, scratch that idea, because print_r() also gives that error...)
Ok, heh. This was my bad. I had thrown an indiscriminant var_dump(debug_backtrace()) at the top of getDefinition, and not wrapped it in a if ($plugin_id == 'ckeditor') check. Turns out, lots of things are plugins. ;)
if ($plugin_id == 'ckeditor') { echo '<pre>' . print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), 1) . '</pre>'; }That works, and gets me this output:
https://gist.github.com/4618988
Now I at least start seeing entity/edit-related things which gives me a bone. Stay tuned...
#2
Actually, I'm calling it a night. here are the breadcrumbs that chx threw, based on his experience w/ entity query for config entities:
It's really important to me though that someone without a batphone to chx is able to figure this out themselves.
so what i wanted to show you isthe __construct of EntityManager
because that's where all the entity plugins are discovered
and it's untrivial to find
it almost never shows up in the backtraces
cos what happens is that eventually you end in EntityManager::getDefinitions which on a cache miss calls the parent which does $this->discovery->getDefinitions(); and then wtf is $this->discovery????
and THAT is put together in the EntityManager constructor
so, read it
so to summarize, the defintiion is put together in the EntityManager constructor and then handed around
Also, while I don't really want to re-open #1852514: Directory structure is fail, part 2: Drupal directories, I was nevertheless completely stumped on how to get from "Drupal\editor\Plugin\Core\Entity\Editor" to core/modules/editor/lib/Drupal/editor/Plugin/Core/Entity/Editor.php. I think we need a (non-aggro) meta issue to discuss this, because that's super hard right now.
#3
I think the issue is that there is no ckeditor plugin?
I can't find one in core http://drupalcode.org/project/drupal.git?a=search&h=HEAD&st=grep&s=ckeditor
This isn't being found by the editor plugin manager based on the above.
Is it something you are working on too? If so can you paste it here too?
#4
Ok. So what this ended up being is that I had copied over the contents of standard_install(), but hadn't copied its yml files over in order to create the filtered HTML / full HTML text formats, because I really shouldn't work on coding at 1am. So in other words, CKEditor was trying to attach to a text format that wasn't there. Makes sense why that would blow up.
Now can someone tell me how I could've discovered that was the problem, given the debugging information at hand?
#5
@larowlan: Yeah, this is in the Spark distribution where we have #1890502: WYSIWYG: Add CKEditor module to core (among other patches) applied. So that part's ok. :)
#6
Filed #1897762: Improve exception handling in case of NULL from getPluginClass as a start.