sgd_dashboard-1.0.0-beta1/src/Plugin/SgdCompanion/SgdCompanionSgdProjects.php
src/Plugin/SgdCompanion/SgdCompanionSgdProjects.php
<?php
namespace Drupal\sgd_dashboard\Plugin\SgdCompanion;
use Drupal\sgd_dashboard\SgdCompanionPluginBase;
/**
* Provides a SGD Companion plugin.
*
* Note that while companion plugins usually have a partner module that resides
* on the target websites and provides the data the plugin handles this one
* does not as its data is derived from the dashboard core modules.
*
* @SgdCompanion(
* id = "sgd_companion_sgd_projects",
* )
*/
class SgdCompanionSgdProjects extends SgdCompanionPluginBase {
/**
* {@inheritdoc}
*
* This plugin doesnt handle the status response as all the project info is
* captured by the core module elsewhere.
*/
public function canProcessStatus($statusData) : bool {
return FALSE;
}
/**
* {@inheritdoc}
*
* We dont handle status info in this plugin so just return false.
*/
public function saveStatus($websiteData, $statusData, $enabledProjects = NULL) : bool {
return FALSE;
}
/**
* {@inheritdoc}
*
* We dont handle status info in this plugin so just return an empty array.
*/
public function getStatusDefaults() : array {
return [];
}
/**
* {@inheritdoc}
*/
public function getStatus($websiteData) : array | NULL {
$data = [];
$websiteId = $websiteData->getParentNodeId();
// Get all the module/project information for the website.
$query = \Drupal::entityQuery('sgd_enabled_project')
->condition('website', $websiteId)
->accessCheck(FALSE);
$storageIds = $query->execute();
// If we have some IDs then get all the entities and process.
if ($storageIds) {
$projectEntities = \Drupal::entityTypeManager()->getStorage('sgd_enabled_project')->loadMultiple($storageIds);
// Get all the data we need into an easier form to work with.
$projects = [];
foreach ($projectEntities as $projectEntity) {
// Don't include core project status here.
if ($projectEntity->project_type->value <> 'core') {
$projects[] = [
'id' => $projectEntity->id(),
'name' => $projectEntity->name->value,
'title' => $projectEntity->title->value,
'type' => $projectEntity->project_type->value,
'status' => $projectEntity->status_id->value,
'installed_version' => $projectEntity->existing_version->value,
'recommended_version' => $projectEntity->recommended->value,
'latest_version' => $projectEntity->latest_version->value,
];
}
}
// Now add to the return array
// Number of enabled modules.
$filteredProjects = array_filter($projects, function ($v) {
return $v['type'] == 'module';
});
$data['sgd_modules_count'] = [
'title' => 'Enabled projects count',
'description' => "The number of enabled projects.",
'value' => count($filteredProjects),
];
// Number of enabled themes.
$filteredProjects = array_filter($projects, function ($v) {
return $v['type'] == 'theme';
});
$data['sgd_themes_count'] = [
'title' => 'Enabled theme count',
'description' => "The number of enabled themes.",
'value' => count($filteredProjects),
];
// Projects that are up-to-date.
$filteredProjects = array_filter($projects, function ($v) {
return $v['status'] == '5';
});
$value = count($filteredProjects);
$data['sgd_projects_up_to_date'] = [
'title' => 'Projects that are up-to-date',
'description' => "The number of projects that are up-to-date.",
'value' => $value,
];
// Projects with security updates.
$filteredProjects = array_filter($projects, function ($v) {
return $v['status'] == '1';
});
$data['sgd_projects_table_data']['security'] = $filteredProjects;
$value = count($filteredProjects);
$data['sgd_projects_security_updates'] = [
'title' => 'Projects with security updates',
'description' => "The number of projects with available security updates.",
'value' => $value,
];
// Projects unsupported.
$filteredProjects = array_filter($projects, function ($v) {
return ($v['status'] == '2' || $v['status'] == '3');
});
$data['sgd_projects_table_data']['unsupported'] = $filteredProjects;
$value = count($filteredProjects);
$data['sgd_projects_unsupported'] = [
'title' => 'Projects no longer supported',
'description' => "The number of projects whose release is no longer supported.",
'value' => $value,
];
// Projects with available updates.
$filteredProjects = array_filter($projects, function ($v) {
return $v['status'] == '4';
});
$data['sgd_projects_table_data']['updates'] = $filteredProjects;
$value = count($filteredProjects);
$data['sgd_projects_updates_available'] = [
'title' => 'Projects with updates available',
'description' => "The number of projects with updated releases available.",
'value' => $value,
];
}
return $data;
}
/**
* {@inheritdoc}
*/
public function getBuildElements($websiteData) : array | NULL {
if ($data = $this->getStatus($websiteData)) {
$elements = [];
$validation = $this->validate($data);
foreach ($data as $key => $value) {
if ($key != 'sgd_projects_table_data') {
$elements[$key] = [
'title' => $value['title'],
'value' => $value['value'],
'status' => $validation[$key] ?? NULL,
];
}
}
$elements['sgd_projects_table_data'] = $data['sgd_projects_table_data'];
return $elements;
}
return NULL;
}
/**
* Validate data.
*
* Checks each item and returns a good/nuetral/bad status that can be
* displayed on page or in a report.
*/
private function validate(&$statusData): array {
$validation = [];
// Validate User variables
// Each validation is hard coded as it differs for each plugin.
foreach ($statusData as $key => $status) {
switch ($key) {
case 'sgd_projects_security_updates':
if ($status['value'] > 0) {
$msgText = [];
$msgText[] = $this->t('The site has security updates avalable for some of its enabled projects.');
$msgText[] = $this->t('Insecure projects should updated to secure releases as a matter of urgency.');
$msgText[] = $this->t('Failing to update to secure releases could jeopordise the security of the website.');
$validation[$key] = [
'class' => 'error',
'text' => $this->t('Issue'),
'message' => implode(' ', $msgText),
];
}
else {
$validation[$key] = [
'class' => 'ok',
'text' => $this->t('OK'),
];
}
break;
case 'sgd_projects_unsupported':
if ($status['value'] > 0) {
$msgText = [];
$msgText[] = $this->t('The site has projects whose release is no longer supported. Unsupported releases no longer receive security coverage');
$msgText[] = $this->t('and as the number of websites using such projects will reduce overtime they may contain unknown security issues.');
$msgText[] = $this->t('Consider updating them to supported releases ASAP.');
$validation[$key] = [
'class' => 'error',
'text' => $this->t('Issue'),
'message' => implode(' ', $msgText),
];
}
else {
$validation[$key] = [
'class' => 'ok',
'text' => $this->t('OK'),
];
}
break;
case 'sgd_projects_updates_available':
if ($status['value'] > 0) {
$msgText = [];
$msgText[] = $this->t('The site has projects with updated releases available. Failing to keep up with project releases increases the chances of issues');
$msgText[] = $this->t('and regressions when they are actually updated. Consider updating to the latest releases as part of your next deployment cycle.');
$validation[$key] = [
'class' => 'warning',
'text' => $this->t('Alert'),
'message' => implode(' ', $msgText),
];
}
else {
$validation[$key] = [
'class' => 'ok',
'text' => $this->t('OK'),
];
}
break;
}
}
return $validation;
}
}
