class DebugForm in CMS Content Sync 8
Same name and namespace in other branches
- 2.1.x src/Form/DebugForm.php \Drupal\cms_content_sync\Form\DebugForm
- 2.0.x src/Form/DebugForm.php \Drupal\cms_content_sync\Form\DebugForm
Content Sync advanced debug form.
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\Core\Form\ConfigFormBase uses ConfigFormBaseTrait
- class \Drupal\cms_content_sync\Form\DebugForm
- class \Drupal\Core\Form\ConfigFormBase uses ConfigFormBaseTrait
Expanded class hierarchy of DebugForm
1 string reference to 'DebugForm'
File
- src/
Form/ DebugForm.php, line 26
Namespace
Drupal\cms_content_sync\FormView source
class DebugForm extends ConfigFormBase {
/**
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
*/
protected $bundleInfoService;
/**
* @var \Drupal\Core\Entity\EntityFieldManager
*/
protected $entityFieldManager;
/**
* Constructs an object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity query
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info_service
* The bundle info service
* @param \Drupal\Core\Entity\EntityFieldManager $entity_field_manager
* The entity field manager
*/
public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $bundle_info_service, EntityFieldManager $entity_field_manager) {
parent::__construct($config_factory);
$this->entityTypeManager = $entity_type_manager;
$this->bundleInfoService = $bundle_info_service;
$this->entityFieldManager = $entity_field_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('config.factory'), $container
->get('entity_type.manager'), $container
->get('entity_type.bundle.info'), $container
->get('entity_field.manager'));
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'cms_content_sync_debug_form';
}
/**
* Display debug output for a given entity to analyze it's sync structure.
*
* @param array $form
*
* @return AjaxResponse|array
* The debug output table
*/
public function inspectEntity($form, FormStateInterface $form_state) {
$entity_type = $form_state
->getValue([
'cms_content_sync_inspect_entity',
'entity_type',
]);
$entity_id = $form_state
->getValue([
'cms_content_sync_inspect_entity',
'entity_id',
]);
$result = [];
if ($entity_type && $entity_id) {
$storage = $this->entityTypeManager
->getStorage($entity_type);
$entity = $storage
->load($entity_id);
if (!$entity) {
$form_state
->setError($form['cms_content_sync_inspect_entity']['entity_id'], 'This entity doesn\'t exist.');
return $result;
}
}
$ajax_response = new AjaxResponse();
if ($entity) {
$result = [
'#type' => 'table',
'#sticky' => true,
'#header' => array_merge([
$this
->t('Label'),
$this
->t('Entity Type'),
$this
->t('Bundle'),
$this
->t('ID'),
$this
->t('UUID'),
$this
->t('Entity Status ID'),
$this
->t('Flow'),
$this
->t('Pool'),
$this
->t('Flags'),
$this
->t('Last push / edit date'),
$this
->t('Last pull'),
$this
->t('Latest log messages'),
]),
];
$this
->debugEntity($result, $entity);
$ajax_response
->addCommand(new HtmlCommand('.cms_content_sync-inspect-entity-output', $result));
$serializer = \Drupal::service('serializer');
$data = $serializer
->serialize($entity, 'json', [
'plugin_id' => 'entity',
]);
$entity_data = '<b>Entity Data:</b><br>';
$entity_data .= '<br><pre><code>' . $data . '</code></pre>';
$ajax_response
->addCommand(new HtmlCommand('.cms_content_sync-inspect-entity-data-output', $entity_data));
}
return $ajax_response;
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['#tree'] = true;
$settings = ContentSyncSettings::getInstance();
$form['cms_content_sync_login'] = [
'#type' => 'submit',
'#value' => $this
->t('Login at Sync Core'),
];
// The extended entity export/import logging is stored within the key value table
// since we do not want this stored within the Drupal configuration.
$form['cms_content_sync_extended_entity_export_logging'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Extended Entity Export logging'),
'#default_value' => $settings
->getExtendedEntityExportLogging() ?? 0,
'#description' => $this
->t('When the "Extended Entity Export logging" is enabled, Content Sync is going to add a log entry to Watchdog
showing all entity values processed by content sync after the <b><u>export</u></b>. This is helpful to debug outgoing entities.<br>
<b>This will create many large log messages, so only use this for a short period of time and disable it immediately after your debugging session.</b>'),
];
$form['cms_content_sync_extended_entity_import_logging'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Extended Entity Import logging'),
'#default_value' => $settings
->getExtendedEntityImportLogging() ?? 0,
'#description' => $this
->t('When the "Extended Entity Import logging" is enabled, Content Sync is going to add a log entry to Watchdog
showing all entity values processed by content sync after the <b><u>import</u></b>. This is helpful to identify if an entity
has changed after content sync has processed it.<br>
<b>This will create many large log messages, so only use this for a short period of time and disable it immediately after your debugging session.</b>'),
];
$form['cms_content_sync_inspect_entity'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Inspect entity'),
];
$entity_types = $this->entityTypeManager
->getDefinitions();
$field_map = $this->entityFieldManager
->getFieldMap();
$entity_types_names = [];
foreach ($entity_types as $type_key => $entity_type) {
// This entity type doesn't contain any fields.
if (!isset($field_map[$type_key])) {
continue;
}
if ('cms_content_sync' == $entity_type
->getProvider()) {
continue;
}
$entity_types_names[$type_key] = $type_key;
}
$form['cms_content_sync_inspect_entity']['entity_type'] = [
'#type' => 'select',
'#title' => $this
->t('Entity type'),
'#options' => $entity_types_names,
'#default_value' => 'node',
];
$form['cms_content_sync_inspect_entity']['entity_id'] = [
'#type' => 'textfield',
'#title' => $this
->t('Entity ID'),
];
$form['cms_content_sync_inspect_entity']['submit'] = [
'#type' => 'button',
'#value' => $this
->t('Check'),
'#ajax' => [
'callback' => '::inspectEntity',
'wrapper' => 'cms_content_sync-inspect-entity-output',
],
];
$form['cms_content_sync_inspect_entity']['entity'] = [
'#prefix' => '<div class="cms_content_sync-inspect-entity-output">',
'#suffix' => '</div>',
];
$form['cms_content_sync_inspect_entity']['entity_data'] = [
'#prefix' => '<div class="cms_content_sync-inspect-entity-data-output">',
'#suffix' => '</div>',
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
$settings = ContentSyncSettings::getInstance();
$settings
->setExtendedEntityExportLogging($form_state
->getValue('cms_content_sync_extended_entity_export_logging'));
$settings
->setExtendedEntityImportLogging($form_state
->getValue('cms_content_sync_extended_entity_import_logging'));
if ('Login at Sync Core' == $form_state
->getValue('op')) {
$messenger = \Drupal::messenger();
foreach (SyncCoreFactory::getAllSyncCores() as $host => $core) {
if ($core
->getSyndicationService()
->refreshAuthentication()) {
$messenger
->addStatus('SUCCESS login from Sync Core at ' . $host);
}
else {
$messenger
->addError('FAILED to login from Sync Core at ' . $host);
}
}
}
}
/**
* @param array $result
* The table render array
* @param \Drupal\Core\Entity\EntityInterface $entity
* @param array $parent_entities
* Entities that have already been processed up the ladder
*/
protected function debugEntity(&$result, $entity, $parent_entities = []) {
$label = str_repeat('+', count($parent_entities)) . ' ';
/*foreach($parent_entities as $parent_entity) {
$label .= $parent_entity->label().' => ';
}*/
$label .= $entity
->label();
$moduleHandler = \Drupal::service('module_handler');
$dblog_enabled = $moduleHandler
->moduleExists('dblog');
if ($dblog_enabled) {
$connection = \Drupal::database();
$log_levels = RfcLogLevel::getLevels();
}
else {
\Drupal::messenger()
->addMessage('dblog is disabled, so no log messages will be displayed.');
}
$children = [];
$infos = EntityStatus::getInfosForEntity($entity
->getEntityTypeId(), $entity
->uuid());
if (!count($infos)) {
return;
}
foreach ($infos as $index => $info) {
$current_row = [];
if (0 == $index) {
$current_row['label'] = [
'#markup' => $label,
];
$current_row['entity_type'] = [
'#markup' => $entity
->getEntityTypeId(),
];
$current_row['bundle'] = [
'#markup' => $entity
->bundle(),
];
$current_row['id'] = [
'#markup' => $entity
->id(),
];
$current_row['uuid'] = [
'#markup' => $entity
->uuid(),
];
}
else {
$current_row['label'] = [
'#markup' => '',
];
$current_row['entity_type'] = [
'#markup' => '',
];
$current_row['bundle'] = [
'#markup' => '',
];
$current_row['id'] = [
'#markup' => '',
];
$current_row['uuid'] = [
'#markup' => '',
];
}
$flow = $info
->getFlow();
$pool = $info
->getPool();
$current_row['entity_status_id'] = [
'#markup' => $info->id->value,
];
$current_row['flow'] = [
'#markup' => $flow ? $flow
->label() : $info
->get('flow')->value,
];
$current_row['pool'] = [
'#markup' => $pool ? $pool
->label() : $info
->get('pool')->value,
];
$current_row['flags'] = [
'#theme' => 'item_list',
];
if ($info
->isSourceEntity()) {
$current_row['flags']['#items'][]['#markup'] = 'Source';
}
if ($info
->isManualPushEnabled()) {
$current_row['flags']['#items'][]['#markup'] = 'Pushing enabled';
}
if ($info
->didUserEnablePush()) {
$current_row['flags']['#items'][]['#markup'] = 'Pushed by user';
}
if ($info
->isPushedAsDependency()) {
$current_row['flags']['#items'][]['#markup'] = 'Pushed as dependency';
}
if ($info
->isOverriddenLocally()) {
$current_row['flags']['#items'][]['#markup'] = 'Overridden locally';
}
$timestamp = $info
->getLastPush();
$current_row['last_export'] = [
'#markup' => $timestamp ? \Drupal::service('date.formatter')
->format($timestamp, 'long') : 'NEVER',
];
$timestamp = $info
->getLastPull();
$current_row['last_import'] = [
'#markup' => $timestamp ? \Drupal::service('date.formatter')
->format($timestamp, 'long') : 'NEVER',
];
$current_row['log_messages'] = [
'#theme' => 'item_list',
'#items' => [],
];
$query = $connection
->select('watchdog', 'w')
->fields('w', [
'timestamp',
'severity',
'message',
'variables',
])
->orderBy('timestamp', 'DESC')
->range(0, 3)
->condition('type', 'cms_content_sync')
->condition('variables', '%' . $connection
->escapeLike($entity
->uuid()) . '%', 'LIKE');
$query = $query
->execute();
$rows = $query
->fetchAll();
foreach ($rows as $res) {
$message = '<strong>' . $log_levels[$res->severity] . '</strong> <em>' . \Drupal::service('date.formatter')
->format($res->timestamp, 'long') . '</em> ' . $this
->formatMessage($res)
->render();
$current_row['log_messages']['#items'][]['#markup'] = $message;
}
$intent = new PushIntent($info
->getFlow(), $info
->getPool(), PushIntent::PUSH_FORCED, SyncIntent::ACTION_CREATE, $entity);
$intent
->execute(true);
$serialized = $intent
->getOperation()
->getData();
foreach ($serialized['embed_entities'] as $child) {
$id = $child[Entity::ENTITY_TYPE_KEY] . $child[Entity::UUID_KEY];
if (isset($children[$id])) {
continue;
}
$children[$id] = $child;
}
$result[] = $current_row;
}
$result[0]['label']['#attributes']['rowspan'] = $index + 1;
$result[0]['entity_type']['#attributes']['rowspan'] = $index + 1;
$result[0]['bundle']['#attributes']['rowspan'] = $index + 1;
$result[0]['id']['#attributes']['rowspan'] = $index + 1;
$result[0]['uuid']['#attributes']['rowspan'] = $index + 1;
/** @var \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository */
$entity_repository = \Drupal::service('entity.repository');
$parent_entities[] = $entity;
foreach ($children as $child) {
$child_entity = $entity_repository
->loadEntityByUuid($child[Entity::ENTITY_TYPE_KEY], $child[Entity::UUID_KEY]);
$this
->debugEntity($result, $child_entity, $parent_entities);
}
}
/**
* Formats a database log message.
*
* @param object $row
* The record from the watchdog table. The object properties are: wid, uid,
* severity, type, timestamp, message, variables, link, name.
*
* @return false|string|TranslatableMarkup
* The formatted log message or FALSE if the message or variables properties
* are not set
*/
protected function formatMessage($row) {
// Check for required properties.
if (isset($row->message, $row->variables)) {
$variables = @unserialize($row->variables);
// Messages without variables or user specified text.
if (null === $variables) {
$message = Xss::filterAdmin($row->message);
}
elseif (!is_array($variables)) {
$message = $this
->t('Log data is corrupted and cannot be unserialized: @message', [
'@message' => Xss::filterAdmin($row->message),
]);
}
else {
$message = $this
->t(Xss::filterAdmin($row->message), $variables);
}
}
else {
$message = false;
}
return $message;
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'cms_content_sync.debug',
];
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ConfigFormBaseTrait:: |
protected | function | Retrieves a configuration object. | |
DebugForm:: |
protected | property | ||
DebugForm:: |
protected | property | ||
DebugForm:: |
protected | property | ||
DebugForm:: |
public | function |
Form constructor. Overrides ConfigFormBase:: |
|
DebugForm:: |
public static | function |
Instantiates a new instance of this class. Overrides ConfigFormBase:: |
|
DebugForm:: |
protected | function | ||
DebugForm:: |
protected | function | Formats a database log message. | |
DebugForm:: |
protected | function |
Gets the configuration names that will be editable. Overrides ConfigFormBaseTrait:: |
|
DebugForm:: |
public | function |
Returns a unique string identifying the form. Overrides FormInterface:: |
|
DebugForm:: |
public | function | Display debug output for a given entity to analyze it's sync structure. | |
DebugForm:: |
public | function |
Form submission handler. Overrides ConfigFormBase:: |
|
DebugForm:: |
public | function |
Form validation handler. Overrides FormBase:: |
|
DebugForm:: |
public | function |
Constructs an object. Overrides ConfigFormBase:: |
|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FormBase:: |
protected | property | The config factory. | 1 |
FormBase:: |
protected | property | The request stack. | 1 |
FormBase:: |
protected | property | The route match. | |
FormBase:: |
protected | function | Gets the config factory for this form. | 1 |
FormBase:: |
private | function | Returns the service container. | |
FormBase:: |
protected | function | Gets the current user. | |
FormBase:: |
protected | function | Gets the request object. | |
FormBase:: |
protected | function | Gets the route match. | |
FormBase:: |
protected | function | Gets the logger for a specific channel. | |
FormBase:: |
protected | function |
Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait:: |
|
FormBase:: |
public | function | Resets the configuration factory. | |
FormBase:: |
public | function | Sets the config factory for this form. | |
FormBase:: |
public | function | Sets the request stack object to use. | |
LinkGeneratorTrait:: |
protected | property | The link generator. | 1 |
LinkGeneratorTrait:: |
protected | function | Returns the link generator. | |
LinkGeneratorTrait:: |
protected | function | Renders a link to a route given a route name and its parameters. | |
LinkGeneratorTrait:: |
public | function | Sets the link generator service. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
UrlGeneratorTrait:: |
protected | property | The url generator. | |
UrlGeneratorTrait:: |
protected | function | Returns the URL generator service. | |
UrlGeneratorTrait:: |
public | function | Sets the URL generator service. | |
UrlGeneratorTrait:: |
protected | function | Generates a URL or path for a specific route based on the given parameters. |