knowledge-8.x-1.x-dev/knowledge.install
knowledge.install
<?php
/**
* @file
* Install, update and uninstall functions for the Knowledge module.
*/
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Implements hook_uninstall().
*/
function knowledge_uninstall() {
// Remove the knowledge fields.
$storage = \Drupal::entityTypeManager()->getStorage('field_storage_config');
$fields = $storage->loadByProperties(['type' => 'knowledge']);
$storage->delete($fields);
// Remove state setting.
\Drupal::state()->delete('knowledge.node_knowledge_statistics_scale');
}
/**
* Implements hook_install().
*/
function knowledge_install() {
// By default, maintain entity statistics for knowledge.
// @see \Drupal\knowledge\KnowledgeStatisticsInterface
\Drupal::state()->set('knowledge.maintain_entity_statistics', TRUE);
// Rebuild user entity form display for mobile number field.
$storage = \Drupal::entityTypeManager()->getStorage('entity_form_display');
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $user_form_display */
$user_form_display = $storage->load('user.user.default');
if (!$user_form_display) {
$user_form_display = $storage->create([
'targetEntityType' => 'user',
'bundle' => 'user',
'mode' => 'default',
'status' => TRUE,
]);
}
$user_form_display
->setComponent('knowledge_coach', [
'type' => 'entity_reference_autocomplete',
'weight' => 14,
'settings' => [
'match_operator' => 'CONTAINS',
'size' => '60',
'placeholder' => '',
'match_limit' => 10,
],
])
->setComponent('knowledge_leader', [
'type' => 'entity_reference_autocomplete',
'weight' => 14,
'settings' => [
'match_operator' => 'CONTAINS',
'size' => '60',
'placeholder' => '',
'match_limit' => 10,
],
])
->save();
}
/**
* Implements hook_schema().
*/
function knowledge_schema() {
$schema['knowledge_entity_statistics'] = [
'description' => 'Maintains statistics of entity and knowledge posts to show "new" and "updated" flags.',
'fields' => [
'entity_id' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The entity_id of the entity for which the statistics are compiled.',
],
'entity_type' => [
'type' => 'varchar_ascii',
'not null' => TRUE,
'default' => 'node',
'length' => EntityTypeInterface::ID_MAX_LENGTH,
'description' => 'The entity_type of the entity to which this knowledge is a reply.',
],
'field_name' => [
'type' => 'varchar_ascii',
'not null' => TRUE,
'default' => '',
'length' => FieldStorageConfig::NAME_MAX_LENGTH,
'description' => 'The field_name of the field that was used to add this knowledge.',
],
'first_knowledge' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The {knowledge}.kid of the first knowledge.',
],
'first_knowledge_timestamp' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp of the first knowledge that was linked within this node, from {knowledge}.changed.',
],
'first_knowledge_uid' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The user ID of the first author to link a knowledge on this node, from {knowledge}.uid.',
],
'last_knowledge' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The {knowledge}.kid of the last knowledge.',
],
'last_knowledge_timestamp' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp of the last knowledge that was posted within this node, from {knowledge}.changed.',
],
'last_knowledge_uid' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The user ID of the latest author to post a knowledge on this node, from {knowledge}.uid.',
],
'total_count' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The total number of knowledge on this entity.',
],
'short_count' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The recent number of knowledge on this entity.',
],
'medium_count' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The medium number of knowledge on this entity.',
],
'long_count' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The long number of knowledge on this entity.',
],
'state_count' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The number of links with the current state.',
],
'state_citation' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The number of citations with the current state.',
],
'total_citation' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The total number of citations on this entity.',
],
'short_citation' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The recent number of citations on this entity.',
],
'medium_citation' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The medium number of citations on this entity.',
],
'long_citation' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The long number of citations on this entity.',
],
],
'primary key' => ['entity_id', 'entity_type', 'field_name'],
'indexes' => [
'last_knowledge_timestamp' => ['last_knowledge_timestamp'],
'total_count' => ['total_count'],
'last_knowledge_uid' => ['last_knowledge_uid'],
],
'foreign keys' => [
'last_knowledge_author' => [
'table' => 'users',
'columns' => [
'last_knowledge_uid' => 'uid',
],
],
],
];
$schema['knowledge_node_statistics'] = [
'description' => 'Statistics about nodes',
'fields' => [
'name' => [
'type' => 'varchar',
'not null' => TRUE,
'length' => 255,
],
'start' => [
'type' => 'int',
'not null' => TRUE,
],
'end' => [
'type' => 'int',
'not null' => TRUE,
],
'entity_type' => [
'type' => 'varchar',
'not null' => TRUE,
'length' => 32,
],
'entity_id' => [
'type' => 'int',
'not null' => TRUE,
],
'period' => [
'type' => 'int',
'not null' => TRUE,
],
'value' => [
'type' => 'int',
'not null' => TRUE,
],
'processed' => [
'type' => 'int',
'not null' => TRUE,
],
],
'primary key' => [
'name',
'start',
'end',
'entity_type',
'entity_id',
'period',
],
];
return $schema;
}
/**
* Competency refactor, removes 'Field Group' dependency.
*/
function knowledge_update_8103(&$sandbox) {
$fields = [
'field_audience' => 'knowledge_publisher',
'field_business' => 'knowledge_contributor',
'field_capture_context' => 'knowledge_publisher',
'field_capture_in_the_moment' => 'knowledge_publisher',
'field_collaborate' => 'knowledge_publisher',
'field_complete_thoughts' => 'knowledge_contributor',
'field_confidence' => 'knowledge_publisher',
'field_content_standard' => 'knowledge_publisher',
'field_documents_request' => 'knowledge_contributor',
'field_fix_it' => 'knowledge_contributor',
'field_flag_it' => 'knowledge_candidate',
'field_improve' => 'knowledge_publisher',
'field_includes_context' => 'knowledge_contributor',
'field_iterative_search' => 'knowledge_publisher',
'field_kcs_article_elements' => 'knowledge_contributor',
'field_link_it' => 'knowledge_candidate',
'field_one' => 'knowledge_contributor',
'field_process_adherence' => 'knowledge_publisher',
'field_relevant' => 'knowledge_publisher',
'field_reuse' => 'knowledge_contributor',
'field_search_it' => 'knowledge_candidate',
'field_solve_loop' => 'knowledge_contributor',
'field_structure' => 'knowledge_contributor',
'field_sufficient_to_solve' => 'knowledge_publisher',
'field_update_or_create' => 'knowledge_contributor',
];
if (!isset($sandbox['progress'])) {
// This must be the first run. Initialize the sandbox.
$sandbox['progress'] = 0;
$sandbox['max'] = 6;
}
// Create knowledge.competency.settings.
if ($sandbox['progress'] == 1) {
$settings = \Drupal::service('config.factory')
->getEditable('knowledge.competency.settings');
$roles = [
[
'role' => 'knowledge_candidate',
'weight' => 0,
'action' => 'auto',
'promote' => 'self',
],
[
'role' => 'knowledge_contributor',
'weight' => 1,
'action' => 'auto',
'promote' => 'self',
],
[
'role' => 'knowledge_publisher',
'weight' => 2,
'action' => 'auto',
'promote' => 'self',
],
];
$settings->set('roles', $roles);
$settings->save();
// Field definition settings.
$fields_definitions = \Drupal::service('entity_field.manager')
->getFieldDefinitions('knowledge_competency', 'knowledge_competency');
foreach ($fields as $field_id => $role) {
$fields_definitions[$field_id]->setThirdPartySetting('knowledge', 'competency_role', $role);
$fields_definitions[$field_id]->save();
}
}
// Install new dependency.
if ($sandbox['progress'] == 2) {
// Install the.
\Drupal::service('module_installer')->install(['knowledge_field'], TRUE);
// Clear Cache.
drupal_flush_all_caches();
}
// Adds new fields.
if ($sandbox['progress'] == 3) {
$roles_field_definition = BaseFieldDefinition::create('knowledge_competency_role')
->setLabel(t('Roles'))
->setDescription(t('The roles of the user.'))
->setRevisionable(TRUE)
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'knowledge_competency_role',
'weight' => 0,
])
->setDisplayOptions('form', [
'type' => 'knowledge_competency_role',
'weight' => 5,
])
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);
\Drupal::entityDefinitionUpdateManager()
->installFieldStorageDefinition('roles', 'knowledge_competency', 'knowledge_competency', $roles_field_definition);
$completed = BaseFieldDefinition::create('timestamp')
->setLabel(t('Completed'))
->setDescription(t('The time that correct = total.'))
->setRevisionable(FALSE)
->setDisplayConfigurable('form', FALSE)
->setDisplayConfigurable('view', TRUE);
\Drupal::entityDefinitionUpdateManager()
->installFieldStorageDefinition('completed', 'knowledge_competency', 'knowledge_competency', $completed);
}
// Adds 'roles' data to revisions.
if ($sandbox['progress'] == 4) {
$database = \Drupal::database();
if (!isset($sandbox['competency_ids'])) {
$database->update('knowledge_competency')
->isNull('completed')
->isNotNull('publisher_proposed')
->expression('completed', 'publisher_proposed')
->execute();
$sandbox['competency_ids'] = \Drupal::entityQuery('knowledge_competency')
->accessCheck(FALSE)
->execute();
$sandbox['competency_total'] = count($sandbox['competency_ids']);
}
else {
$competency_id = array_pop($sandbox['competency_ids']);
$query = $database->select('knowledge_competency_revision', 'kcr');
$query->addField('kcr', 'vid');
$query->condition('id', $competency_id);
$revision_ids = $query->execute()->fetchAll();
$competency_storage = \Drupal::entityTypeManager()->getStorage('knowledge_competency');
$entity = $competency_storage->load($competency_id);
$score = [
'knowledge_candidate' => [
'correct' => 0,
'total' => 0,
],
'knowledge_contributor' => [
'correct' => 0,
'total' => 0,
],
'knowledge_publisher' => [
'correct' => 0,
'total' => 0,
],
];
foreach ($fields as $field => $role) {
$score[$role]['total'] += 1;
if ($entity->get($field)->value) {
$score[$role]['correct'] += 1;
}
$score[$role]['completed'] = ($score[$role]['correct'] == $score[$role]['total'])
? $entity->get('revision_timestamp')->value
: NULL;
}
$database->insert('knowledge_competency__roles')
->fields([
'bundle',
'deleted',
'entity_id',
'langcode',
'delta',
'roles_role',
'roles_correct',
'roles_total',
'roles_proposer',
'roles_approver',
'roles_proposed',
'roles_approved',
'revision_id',
])
->values([
'bundle' => 'knowledge_competency',
'deleted' => 0,
'entity_id' => $competency_id,
'langcode' => 'en',
'delta' => 0,
'roles_role' => 'knowledge_candidate',
'roles_correct' => $score['knowledge_candidate']['correct'],
'roles_total' => $score['knowledge_candidate']['total'],
'roles_proposer' => NULL,
'roles_approver' => NULL,
'roles_proposed' => $score['knowledge_candidate']['completed'],
'roles_approved' => $score['knowledge_candidate']['completed'],
'revision_id' => $entity->getRevisionId(),
])
->values([
'bundle' => 'knowledge_competency',
'deleted' => 0,
'entity_id' => $competency_id,
'langcode' => 'en',
'delta' => 1,
'roles_role' => 'knowledge_contributor',
'roles_correct' => $score['knowledge_contributor']['correct'],
'roles_total' => $score['knowledge_contributor']['total'],
'roles_proposer' => NULL,
'roles_approver' => NULL,
'roles_proposed' => $score['knowledge_contributor']['completed'],
'roles_approved' => $score['knowledge_contributor']['completed'],
'revision_id' => $entity->getRevisionId(),
])
->values([
'bundle' => 'knowledge_competency',
'deleted' => 0,
'entity_id' => $competency_id,
'langcode' => 'en',
'delta' => 2,
'roles_role' => 'knowledge_publisher',
'roles_correct' => $score['knowledge_publisher']['correct'],
'roles_total' => $score['knowledge_publisher']['total'],
'roles_proposer' => $entity->get('publisher_coach')?->target_id,
'roles_approver' => $entity->get('publisher_leader')?->target_id,
'roles_proposed' => $entity->get('publisher_proposed')->value,
'roles_approved' => $entity->get('publisher_approved')->value,
'revision_id' => $entity->getRevisionId(),
])->execute();
foreach ($revision_ids as $id => $vid) {
$revision = $competency_storage->loadRevision($vid->vid);
$score = [
'knowledge_candidate' => [
'correct' => 0,
'total' => 0,
],
'knowledge_contributor' => [
'correct' => 0,
'total' => 0,
],
'knowledge_publisher' => [
'correct' => 0,
'total' => 0,
],
];
foreach ($fields as $field => $role) {
$score[$role]['total'] += 1;
if ($revision->get($field)->value) {
$score[$role]['correct'] += 1;
}
$score[$role]['completed'] = ($score[$role]['correct'] == $score[$role]['total'])
? $revision->get('revision_timestamp')->value
: NULL;
}
$database->insert('knowledge_competency_revision__roles')
->fields([
'bundle',
'deleted',
'entity_id',
'langcode',
'delta',
'roles_role',
'roles_correct',
'roles_total',
'roles_proposer',
'roles_approver',
'roles_proposed',
'roles_approved',
'revision_id',
])
->values([
'bundle' => 'knowledge_competency',
'deleted' => 0,
'entity_id' => $competency_id,
'langcode' => 'en',
'delta' => 0,
'roles_role' => 'knowledge_candidate',
'roles_correct' => $score['knowledge_candidate']['correct'],
'roles_total' => $score['knowledge_candidate']['total'],
'roles_proposer' => NULL,
'roles_approver' => NULL,
'roles_proposed' => $score['knowledge_candidate']['completed'],
'roles_approved' => $score['knowledge_candidate']['completed'],
'revision_id' => $vid->vid,
])
->values([
'bundle' => 'knowledge_competency',
'deleted' => 0,
'entity_id' => $competency_id,
'langcode' => 'en',
'delta' => 1,
'roles_role' => 'knowledge_contributor',
'roles_correct' => $score['knowledge_contributor']['correct'],
'roles_total' => $score['knowledge_contributor']['total'],
'roles_proposer' => NULL,
'roles_approver' => NULL,
'roles_proposed' => $score['knowledge_contributor']['completed'],
'roles_approved' => $score['knowledge_contributor']['completed'],
'revision_id' => $vid->vid,
])
->values([
'bundle' => 'knowledge_competency',
'deleted' => 0,
'entity_id' => $competency_id,
'langcode' => 'en',
'delta' => 2,
'roles_role' => 'knowledge_publisher',
'roles_correct' => $score['knowledge_publisher']['correct'],
'roles_total' => $score['knowledge_publisher']['total'],
'roles_proposer' => $entity->get('publisher_coach')?->target_id,
'roles_approver' => $entity->get('publisher_leader')?->target_id,
'roles_proposed' => $entity->get('publisher_proposed')->value,
'roles_approved' => $entity->get('publisher_approved')->value,
'revision_id' => $vid->vid,
])->execute();
}
}
$remaining_competency = count($sandbox['competency_ids']);
if ($remaining_competency) {
$competency_total = $sandbox['competency_total'];
$sandbox['#finished'] = ($competency_total - $remaining_competency) / $competency_total;
return;
}
}
$sandbox['progress'] += 1;
$sandbox['#finished'] = empty($sandbox['max']) ? 1 : $sandbox['progress'] / $sandbox['max'];
// Updates existing field definitions.
if ($sandbox['progress'] == 6) {
$sandbox = [];
\Drupal::entityTypeManager()->clearCachedDefinitions();
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
$entity_type = $definition_update_manager->getEntityType('knowledge_competency');
$entity_type->set('class', 'Drupal\knowledge\Entity\Competency');
$entity_type->set('admin_permission', 'administer knowledge_competency');
$handlers = $entity_type->get('handlers');
$handlers['storage'] = 'Drupal\knowledge\CompetencyStorage';
$handlers['list_builder'] = 'Drupal\knowledge\CompetencyListBuilder';
$handlers['views_data'] = 'Drupal\knowledge\CompetencyViewsData';
$handlers['form'] = [
'default' => 'Drupal\knowledge\Form\CompetencyForm',
'add' => 'Drupal\knowledge\Form\CompetencyForm',
'edit' => 'Drupal\knowledge\Form\CompetencyForm',
'delete' => 'Drupal\knowledge\Form\CompetencyDeleteForm',
'approve' => 'Drupal\knowledge\Form\CompetencyApproveForm',
];
$handlers['route_provider']['html'] = 'Drupal\knowledge\CompetencyHtmlRouteProvider';
$handlers['access'] = 'Drupal\knowledge\CompetencyAccessControlHandler';
$entity_type->set('handlers', $handlers);
$field_storage_definitions = $last_installed_schema_repository->getLastInstalledFieldStorageDefinitions('knowledge_competency');
$field_storage_definitions['user_id']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['contributor_coach']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['contributor_coach']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['contributor_leader']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['contributor_leader']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['publisher_coach']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['publisher_coach']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['publisher_leader']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['publisher_leader']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['contributor_proposed']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['contributor_proposed']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['contributor_approved']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['contributor_approved']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['publisher_proposed']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['publisher_proposed']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['publisher_approved']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['publisher_approved']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['candidate_correct']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['candidate_correct']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['candidate_total']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['candidate_total']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['contributor_correct']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['contributor_correct']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['contributor_total']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['contributor_total']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['publisher_correct']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['publisher_correct']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['publisher_total']->setDisplayConfigurable('form', FALSE);
$field_storage_definitions['publisher_total']->setDisplayConfigurable('view', FALSE);
$field_storage_definitions['correct']->setDisplayConfigurable('view', TRUE);
$field_storage_definitions['total']->setDisplayConfigurable('view', TRUE);
$definition_update_manager->updateFieldableEntityType($entity_type, $field_storage_definitions, $sandbox);
}
}
/**
* Remove RSS displays from views that use the knowledge_rss row plugin.
*
* The RSS functionality has been removed from Drupal core in 11.3.0.
*/
function knowledge_update_8104() {
$config_factory = \Drupal::configFactory();
$modified_views = [];
// Load all view configurations.
foreach ($config_factory->listAll('views.view.') as $view_config_name) {
$view = $config_factory->getEditable($view_config_name);
$displays = $view->get('display');
$modified = FALSE;
if (!empty($displays)) {
foreach ($displays as $display_id => $display) {
// Check if this display uses the knowledge_rss row plugin.
if (isset($display['display_options']['row']['type']) && $display['display_options']['row']['type'] === 'knowledge_rss') {
// Remove this display.
unset($displays[$display_id]);
$modified = TRUE;
\Drupal::logger('knowledge')->notice('Removed RSS display "@display_id" from view "@view" as the knowledge_rss row plugin has been removed.', [
'@display_id' => $display_id,
'@view' => $view->get('id'),
]);
}
}
// Save the modified view if displays were removed.
if ($modified) {
$view->set('display', $displays);
$view->save();
$modified_views[] = $view->get('label') ?: $view->get('id');
}
}
}
if (!empty($modified_views)) {
return t('Removed RSS displays from the following views: @views. The RSS functionality has been removed from Drupal core.', [
'@views' => implode(', ', $modified_views),
]);
}
return t('No views with knowledge_rss displays were found.');
}
