knowledge-8.x-1.x-dev/src/Plugin/Block/ArticleTypes.php
src/Plugin/Block/ArticleTypes.php
<?php
namespace Drupal\knowledge\Plugin\Block;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides the "Article Types" block.
*
* @Block(
* id = "knowledge_article_type",
* admin_label = @Translation("Article Types"),
* category = @Translation("Knowledge")
* )
*/
class ArticleTypes extends BlockBase implements ContainerFactoryPluginInterface {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* The time service.
*
* @var \Drupal\Component\Datetime\TimeInterface
*/
protected $time;
/**
* The user storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $userStorage;
/**
* The path current service.
*
* @var \Drupal\Core\Path\CurrentPathStack
*/
protected $pathCurrent;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* ModerationDashboardActivity constructor.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Database\Connection $database
* The database connection.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time service.
* @param \Drupal\Core\Entity\EntityStorageInterface $user_storage
* The user storage.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
* @param \Drupal\Core\Path\CurrentPathStack $path_current
* The path service.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $database, TimeInterface $time, EntityStorageInterface $user_storage, RendererInterface $renderer, CurrentPathStack $path_current, AccountInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->database = $database;
$this->time = $time;
$this->userStorage = $user_storage;
$this->renderer = $renderer;
$this->pathCurrent = $path_current;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('database'),
$container->get('datetime.time'),
$container->get('entity_type.manager')->getStorage('user'),
$container->get('renderer'),
$container->get('path.current'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function build() {
$config = $this->getConfiguration();
$hash = $config['hash'];
$uid = $this->getUid();
$product = $this->getProduct();
$parameters = [];
if ($product != 0) {
$parameters[':product'] = $product;
}
if ($config['context'] != '_none') {
$parameters[':uid'] = $uid;
}
$contentStateQuery = $this->contentTypeQuery();
$states = $this->database->query($contentStateQuery, $parameters)
->fetchAllAssoc('type', \PDO::FETCH_ASSOC);
sort($states);
if (!$states) {
return [
'#markup' => '<p>' . $this->t('There are no knowledge articles.') . '</p>',
];
}
$data = [
'labels' => [],
'datasets' => [
[
'label' => $this->t('type'),
'data' => [],
'backgroundColor' => [],
],
],
];
foreach ($states as $state) {
$data['labels'][] = ucwords(str_replace('_', ' ', $state['type']));
$data['datasets'][0]['data'][] = $state['count'] ?? 0;
$data['datasets'][0]['backgroundColor'][] = 'rgba(' . $this->typeColorSelector($state['type']) . ' .4)';
$data['datasets'][0]['borderColor'][] =
'rgba(' . $this->typeColorSelector($state['type']) . ' .9)';
}
$build = [
'#cache' => [
'contexts' => [],
],
'#type' => 'container',
'#attributes' => [
'class' => ['knowledge-article-types'],
'id' => [$hash],
],
'#attached' => [
'library' => ['knowledge/article_types'],
'drupalSettings' => [
'knowledge_article_type' => [
$hash => $data,
],
],
],
];
$this->renderer->addCacheableDependency($build, $config);
return $build;
}
/**
* {@inheritdoc}
*/
public function blockForm($form, FormStateInterface $form_state) {
$form = parent::blockForm($form, $form_state);
$config = $this->getConfiguration();
$form['context'] = [
'#type' => 'select',
'#title' => $this->t('Context'),
'#description' => $this->t('Context the report is presented.'),
'#default_value' => $config['context'] ?? '_none',
'#options' => [
'_none' => $this->t('None'),
'user' => $this->t('User'),
'current_user' => $this->t('Current User'),
],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
$context = $form_state->getValue('context');
$hash = sha1(serialize([$context]));
$this->setConfigurationValue('context', $context);
$this->setConfigurationValue('hash', $hash);
}
/**
* {@inheritdoc}
*/
public function getCacheTags() {
return Cache::mergeTags(parent::getCacheTags(), [
'config:knowledge.settings.node_types',
]);
}
/**
* Returns the sql query for the count of each article type.
*/
protected function contentTypeQuery() {
$config = $this->getConfiguration();
$product = $this->getProduct();
$sql = "
SELECT type, COUNT(type) as count
FROM {node_field_data}
INNER JOIN {node_revision__field_product_ref} as nrfpr
ON nrfpr.entity_id = nid
INNER JOIN {taxonomy_term_field_data} as ttfd
ON nrfpr.field_product_ref_target_id = tid
WHERE type IN ('q_a', 'how_to', 'solution')
";
if ($config['context'] != '_none') {
$sql .= "
AND uid = :uid
";
}
if ($product != 0) {
$sql .= "
AND tid = :product
";
}
$sql .= "GROUP BY type";
return $sql;
}
/**
* Returns the user id for the context.
*/
protected function getUid() {
$currentPath = $this->pathCurrent->getPath();
$pathArray = explode('user/', $currentPath);
if (count($pathArray) > 1) {
$pathArray = explode('/', $pathArray[1]);
$uid = (int) $pathArray[0];
if (is_int($uid)) {
return $uid;
}
}
return $this->currentUser->id();
}
/**
* Returns the taxonomy id for the context.
*/
protected function getProduct() {
$currentPath = $this->pathCurrent->getPath();
$pathArray = explode('taxonomy/term/', $currentPath);
if (count($pathArray) > 1) {
$pathArray = explode('/', $pathArray[1]);
$product = (int) $pathArray[0];
if (is_int($product)) {
return $product;
}
}
return 0;
}
/**
* Generates a random RGB color.
*/
protected function typeColorSelector($type) {
switch ($type) {
case 'page':
$color = '255, 99, 132,';
break;
case 'how_to':
$color = '54, 162, 235,';
break;
case 'solution':
$color = '37, 190, 136,';
break;
case 'q_a':
$color = '93, 37, 190,';
break;
default:
$color = '0, 0, 0,';
break;
}
return $color;
}
}
