diff --git a/config/install/devel.settings.yml b/config/install/devel.settings.yml index 0ff6745..916f28c 100644 --- a/config/install/devel.settings.yml +++ b/config/install/devel.settings.yml @@ -14,3 +14,4 @@ krumo_skin: 'default' rebuild_theme: FALSE debug_mail_file_format: '%to-%subject-%datetime.mail.txt' debug_mail_directory: 'temporary://devel-mails' +devel_dumper: 'doctrine' diff --git a/config/schema/devel.schema.yml b/config/schema/devel.schema.yml index 99d732a..2c16ae8 100644 --- a/config/schema/devel.schema.yml +++ b/config/schema/devel.schema.yml @@ -53,3 +53,6 @@ devel.settings: debug_mail_directory: type: string label: 'Mail debug directory' + devel_dumper: + type: string + label: 'Devel variable dumper' diff --git a/devel.module b/devel.module index f184831..647a9a6 100644 --- a/devel.module +++ b/devel.module @@ -598,157 +598,12 @@ function t_safe($string, $args) { * @param string $prefix * @todo: this parameter is not needed with Kint. * Prefix for output items. - */ -function kdevel_print_object($object, $prefix = NULL) { - // @todo: quick fix to avoid Kint output floating. Remove when fixed upstream. - return has_kint() ? '
' . @Kint::dump($object) . '
' : devel_print_object($object, $prefix); -} - -/** - * Displays an object or array. - * - * @param array|object $object - * The object or array to display. - * @param string $prefix - * Prefix for the output items (example "$node->", "$user->", "$"). - * @param boolean $header - * Set to FALSE to suppress the output of the h3 tag. - */ -function devel_print_object($object, $prefix = NULL, $header = TRUE) { - $output = '
'; - if ($header) { - $output .= '

' . t('Display of !type !obj', array( - '!type' => str_replace(array('$', '->'), '', $prefix), - '!obj' => gettype($object), - ) - ) . '

'; - } - $output .= _devel_print_object($object, $prefix); - $output .= '
'; - return $output; -} - -/** - * Returns formatted listing for an array or object. - * - * Recursive (and therefore magical) function goes through an array or object - * and returns a nicely formatted listing of its contents. * - * @param array|object $obj - * Array or object to recurse through. - * @param string $prefix - * Prefix for the output items (example "$node->", "$user->", "$"). - * @param string $parents - * Used by recursion. - * @param boolean $object - * Used by recursion. - * - * @return string - * Formatted html. - * - * @todo - * currently there are problems sending an array with a varname + * @deprecated in Devel 8.x-dev, will be removed before Devel 8.0. + * Use devel_dump() instead. */ -function _devel_print_object($obj, $prefix = NULL, $parents = NULL, $object = FALSE) { - static $root_type, $out_format; - - // TODO: support objects with references. See http://drupal.org/node/234581. - if (isset($obj->view)) { - return; - } - - if (!isset($root_type)) { - $root_type = gettype($obj); - if ($root_type == 'object') { - $object = TRUE; - } - } - - if (is_object($obj)) { - $obj = (array) $obj; - } - if (is_array($obj)) { - $output = "
\n"; - foreach ($obj as $field => $value) { - if ($field === 'devel_flag_reference') { - continue; - } - if (!is_null($parents)) { - if ($object) { - $field = $parents . '->' . $field; - } - else { - if (is_int($field)) { - $field = $parents . '[' . $field . ']'; - } - else { - $field = $parents . '[\'' . $field . '\']'; - } - } - } - - $type = gettype($value); - - $show_summary = TRUE; - $summary = NULL; - if ($show_summary) { - switch ($type) { - case 'string': - case 'float': - case 'integer': - if (strlen($value) == 0) { - $summary = t("{empty}"); - } - elseif (strlen($value) < 40) { - $summary = htmlspecialchars($value); - } - else { - $summary = \Drupal::translation()->formatPlural(Unicode::strlen($value), '1 character', '@count characters'); - } - break; - - case 'array': - case 'object': - $summary = \Drupal::translation()->formatPlural(count((array) $value), '1 element', '@count elements'); - break; - - case 'boolean': - $summary = $value ? t('TRUE') : t('FALSE'); - break; - } - } - if (!is_null($summary)) { - $typesum = '(' . $type . ', ' . $summary . ')'; - } - else { - $typesum = '(' . $type . ')'; - } - - $output .= ''; - $output .= "
{$prefix}{$field} $typesum
\n"; - $output .= "
\n"; - // Check for references. - if (is_array($value) && isset($value['devel_flag_reference'])) { - $value['devel_flag_reference'] = TRUE; - } - // Check for references to prevent errors from recursions. - if (is_array($value) && isset($value['devel_flag_reference']) && !$value['devel_flag_reference']) { - $value['devel_flag_reference'] = FALSE; - $output .= _devel_print_object($value, $prefix, $field); - } - elseif (is_object($value)) { - $value->devel_flag_reference = FALSE; - $output .= _devel_print_object((array) $value, $prefix, $field, TRUE); - } - else { - $value = is_bool($value) ? ($value ? 'TRUE' : 'FALSE') : $value; - $output .= htmlspecialchars(print_r($value, TRUE)) . "\n"; - } - $output .= "
\n"; - } - $output .= "
\n"; - } - return $output; +function kdevel_print_object($object, $prefix = NULL) { + return devel_dump($object, TRUE); } /** @@ -890,6 +745,42 @@ function devel_timer() { } /** + * Dumps/exports variable using DevelDumper plugins. + * + * @param mixed $input + * The variable to dump. + * @param bool $return + * (optional) Whether return a string representation of the variable. Defaults + * to FALSE + * @param string $plugin_id + * (optional) The plugin_id for the plugin instance. Defaults to the configured + * plugin or 'doctrine' if the configured plugin isn't found. + * + * @return void|string + * String representation of the variable if $return is TRUE, otherwise nothing. + */ +function devel_dump($input, $return = FALSE, $plugin_id = NULL) { + if (\Drupal::currentUser()->hasPermission('access devel information')) { + /** @var \Drupal\devel\DevelDumperPluginManager $plugin_manager */ + $plugin_manager = \Drupal::service('plugin.manager.devel_dumper'); + + if ($plugin_id && $plugin_manager->hasDefinition($plugin_id)) { + $dumper = $plugin_manager->createInstance($plugin_id); + } + else { + $default = \Drupal::config('devel.settings')->get('devel_dumper'); + $dumper = $plugin_manager->createInstance($default); + } + + if ($return) { + return $dumper->export($input); + } + + $dumper->dump($input); + } +} + +/** * An alias for drupal_debug(). */ function dd($data, $label = NULL) { @@ -1041,20 +932,12 @@ function dvr($input, $return = FALSE, $name = NULL) { /** * Kint print. + * + * @deprecated in Devel 8.x-dev, will be removed before Devel 8.0. + * Use devel_dump() instead. */ function kprint_r($input, $return = FALSE, $name = NULL, $function = 'print_r') { - if (\Drupal::currentUser()->hasPermission('access devel information')) { - // Kint is too heavy to bother with for scalars like strings and integers. - if (merits_kint($input)) { - // Had to use @d() instead of @Kint::dump() as the latter is ignoring @ modifier. - $output = $return ? (isset($name) ? $name . ' => ' : '') . @d($input) : Kint::dump($input); - } - else { - $output = dprint_r($input, $return, $name, $function); - } - - return SafeMarkup::set($output); - } + return devel_dump($input, $return); } /** diff --git a/devel.services.yml b/devel.services.yml index 1a966ec..941a122 100644 --- a/devel.services.yml +++ b/devel.services.yml @@ -16,3 +16,7 @@ services: arguments: ['@csrf_token'] tags: - { name: access_check } + + plugin.manager.devel_dumper: + class: Drupal\devel\DevelDumperPluginManager + parent: default_plugin_manager diff --git a/kint/kint.module b/kint/kint.module index e749bf4..ac0530b 100644 --- a/kint/kint.module +++ b/kint/kint.module @@ -54,5 +54,5 @@ function ksm() { * Load the Kint class. */ function kint_require() { - require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'kint') . '/kint/Kint.class.php'; + return require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'kint') . '/kint/Kint.class.php'; } diff --git a/kint/src/Plugin/DevelDumper/KintDevelDumper.php b/kint/src/Plugin/DevelDumper/KintDevelDumper.php new file mode 100644 index 0000000..42740e4 --- /dev/null +++ b/kint/src/Plugin/DevelDumper/KintDevelDumper.php @@ -0,0 +1,50 @@ +init()) { + \Kint::dump($input); + } + } + + /** + * {@inheritdoc} + */ + public function export($input) { + if ($this->init()) { + return @\Kint::dump($input); + } + } + + /** + * Load the Kint class. + * + * @return bool + * TRUE if Kint class is loaded, FALSE otherwise. + */ + private function init() { + return kint_require(); + } +} diff --git a/src/Annotation/DevelDumper.php b/src/Annotation/DevelDumper.php new file mode 100644 index 0000000..2bf2a55 --- /dev/null +++ b/src/Annotation/DevelDumper.php @@ -0,0 +1,47 @@ +setCacheBackend($cache_backend, 'devel_dumper_plugins'); + } + + /** + * {@inheritdoc} + */ + public function getFallbackPluginId($plugin_id, array $configuration = array()) { + return 'doctrine'; + } + +} diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php index 32564b3..3ea111e 100644 --- a/src/Form/SettingsForm.php +++ b/src/Form/SettingsForm.php @@ -9,6 +9,8 @@ namespace Drupal\devel\Form; use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Form\ConfigFormBase; +use Drupal\devel\DevelDumperPluginManager; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; @@ -19,6 +21,32 @@ use Drupal\Core\Url; class SettingsForm extends ConfigFormBase { /** + * Devel Dumper Plugin Manager. + * + * @var \Drupal\devel\DevelDumperPluginManager + */ + protected $dumperManager; + + /** + * Constructs a new SettingsForm object. + * + * @param \Drupal\devel\DevelDumperPluginManager $devel_dumper_manager + * Devel Dumper Plugin Manager. + */ + public function __construct(DevelDumperPluginManager $devel_dumper_manager) { + $this->dumperManager = $devel_dumper_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.devel_dumper') + ); + } + + /** * {@inheritdoc} */ public function getFormID() { @@ -153,6 +181,22 @@ class SettingsForm extends ConfigFormBase { '#default_value' => $devel_config->get('rebuild_theme'), ); + $options = array(); + foreach ($this->dumperManager->getDefinitions() as $definition) { + $options[$definition['id']] = $definition['label']; + } + + $dumper = $devel_config->get('devel_dumper'); + $default = isset($options[$dumper]) ? $dumper : 'doctrine'; + + $form['dumper'] = array( + '#type' => 'radios', + '#title' => $this->t('Dumper'), + '#options' => $options, + '#default_value' => $default, + '#description' => $this->t('Dumper plugin used for debug variables.'), + ); + return parent::buildForm($form, $form_state); } @@ -174,6 +218,7 @@ class SettingsForm extends ConfigFormBase { ->set('error_handlers', $values['error_handlers']) ->set('krumo_skin', $values['krumo_skin']) ->set('rebuild_theme', $values['rebuild_theme']) + ->set('devel_dumper', $values['dumper']) ->save(); } diff --git a/src/Plugin/DevelDumper/DoctrineDevelDumper.php b/src/Plugin/DevelDumper/DoctrineDevelDumper.php new file mode 100644 index 0000000..7d2d19e --- /dev/null +++ b/src/Plugin/DevelDumper/DoctrineDevelDumper.php @@ -0,0 +1,44 @@ +' . $dump . ''; + } +}