Skip to content
Snippets Groups Projects
Commit d740987e authored by HamzaDwaya's avatar HamzaDwaya
Browse files

Issue #3490127: Add code to utilize Drush Command for extracting all classes into a file

parent 67eed78d
Branches
Tags
No related merge requests found
classes_extractor.settings:
path: '/admin/config/classes-extractor'
defaults:
_form: '\Drupal\classes_extractor\Form\ClassesExtractorConfigForm'
_title_callback: '\Drupal\classes_extractor\Form\ClassesExtractorConfigForm::getTitle'
requirements:
_permission: 'administer site configuration'
options:
_admin_route: TRUE
services:
classes_extractor.manager:
class: Drupal\classes_extractor\ClassesExtractorManager
arguments: ['@entity_type.manager']
classes_extractor.command:
class: Drupal\classes_extractor\Drush\ClassesExtractorCommands
tags:
- { name: drush.command }
<?php
namespace Drupal\classes_extractor;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\filter\Entity\FilterFormat;
use Drupal\layout_builder\SectionComponent;
/**
* Manager Service for Classes Extractor Module.
*/
class ClassesExtractorManager {
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Used of entity type manager.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
*/
/**
* Construct.
*/
public function __construct(
EntityTypeManagerInterface $entity_type_manager,
) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* Get all Classes that set on configuration and content.
*/
public function getClasses() {
$classes = [];
$cacheableMetadata = new CacheableMetadata();
// Load all entity view displays and extract classes.
$entityTypeManager = \Drupal::entityTypeManager();
$displays = $entityTypeManager->getStorage('entity_view_display')->loadMultiple();
foreach ($displays as $display) {
$this->extractDisplayClasses($display, $classes);
}
$cacheableMetadata->addCacheTags(['entity_view_display_list']);
// Load all views and extract classes.
$views = $entityTypeManager->getStorage('view')->loadMultiple();
foreach ($views as $view) {
$this->recursiveGetClasses($view->toArray(), $classes);
}
$cacheableMetadata->addCacheTags(['view_list']);
// Extract global Display Suite classes.
$dsSettings = \Drupal::config('ds.settings');
$globalClasses = $dsSettings->get('classes') ?? [];
$classes = array_merge($classes, $globalClasses['region'] ?? [], $globalClasses['field'] ?? []);
$cacheableMetadata->addCacheableDependency($dsSettings);
// Extract classes from Seeds Layouts module if available.
if (\Drupal::moduleHandler()->moduleExists('seeds_layouts')) {
$seedsLayoutsConfig = \Drupal::config('seeds_layouts.config');
$this->recursiveGetClasses($seedsLayoutsConfig->getRawData(), $classes);
$cacheableMetadata->addCacheableDependency($seedsLayoutsConfig);
}
// Extract classes from Seeds Grid if Seeds Page available.
if (\Drupal::moduleHandler()->moduleExists('seeds_page')) {
$this->extractSeedsGridClasses($classes);
}
// Extract allowed HTML classes from editor configuration.
$this->extractEditorFormatterClasses($classes);
// Flatten, remove duplicates, and filter empty values.
$uniqueClasses = array_unique(array_filter($this->flattenClasses($classes)));
// Transform into key-value pair for final output.
return array_combine($uniqueClasses, $uniqueClasses);
}
/**
* This function used for extract display settings classes.
*/
private function extractDisplayClasses($display, &$classes) {
$components = [
$display->getComponents(),
$display->getThirdPartySetting('ds', 'fields', []),
$display->getThirdPartySetting('ds', 'layout', []),
$display->getThirdPartySetting('ds', 'regions', []),
$display->getThirdPartySettings('field_group'),
$display->getThirdPartySetting('layout_builder', 'sections', []),
];
foreach ($components as $component) {
$this->recursiveGetClasses($component, $classes);
}
// Handle Layout Builder components.
$layoutBuilderSections = $display->getThirdPartySetting('layout_builder', 'sections', []);
foreach ($layoutBuilderSections as $section) {
foreach ($section->getComponents() as $component) {
if ($component instanceof SectionComponent) {
$this->recursiveGetClasses($component->get("configuration"), $classes);
}
}
}
}
/**
* This function used to extract grid classes for seeds page block.
*/
private function extractSeedsGridClasses(&$classes) {
$entityFieldManager = \Drupal::service('entity_field.manager');
$fieldDefinitions = $entityFieldManager->getFieldDefinitions('block_content', 'seeds_grid');
$targetFields = [
$fieldDefinitions['field_seeds_desktop'] ?? NULL,
$fieldDefinitions['field_seeds_tablet'] ?? NULL,
$fieldDefinitions['field_seeds_mobile'] ?? NULL,
];
foreach ($targetFields as $field) {
if ($field) {
$allowedValues = array_keys($field->getFieldStorageDefinition()->getSetting('allowed_values'));
$classes = array_merge($classes, $allowedValues);
}
}
}
/**
* This function to extract the classes on the ckeditor configuration.
*/
private function extractEditorFormatterClasses(&$classes) {
$filterFormat = FilterFormat::load('basic_editor');
$filterHtml = $filterFormat->filters('filter_html');
$config = $filterHtml->getConfiguration();
if (!empty($config['settings']['allowed_html'])) {
preg_match_all('/class="([^"]*)"/', $config['settings']['allowed_html'], $matches);
if (!empty($matches[1])) {
foreach ($matches[1] as $match) {
$classes = array_merge($classes, explode(' ', $match));
}
}
}
}
/**
* This function is used to flatten class.
*/
private function flattenClasses(array $classes): array {
$flattened = [];
foreach ($classes as $class) {
if (is_array($class)) {
$flattened = array_merge($flattened, $this->flattenClasses($class));
}
else {
$flattened[] = $class;
}
}
return $flattened;
}
/**
* Recursively get classes from settings.
*/
public function recursiveGetClasses(array $settings, array &$classes) {
foreach ($settings as $key => $value) {
if (is_array($value)) {
$this->recursiveGetClasses($value, $classes);
}
else {
if (
strpos($key, 'class') !== FALSE
|| strpos($key, 'classes') !== FALSE
) {
if ($value && is_string($value)) {
if (strpos($value, PHP_EOL) !== FALSE) {
$value = explode(PHP_EOL, $value);
foreach ($value as &$v) {
if (strpos($v, '|') !== FALSE) {
$v = explode('|', $v)[0];
}
else {
$v = trim($v);
}
}
$value = implode(' ', $value);
}
$classes[] = $value;
}
}
if (strpos($key, 'attributes') !== FALSE && is_string($value)) {
// Attributes like "class|test best,data-id|2".
$attributes = explode(',', $value);
foreach ($attributes as $attribute) {
$attribute = explode('|', $attribute);
if (count($attribute) === 2 && $attribute[0] === 'class') {
$classes = array_merge($classes, explode(' ', $attribute[1]));
}
}
}
}
}
}
}
<?php
namespace Drupal\classes_extractor\Drush;
use Drush\Commands\DrushCommands;
/**
* Drush command to create a file in Drupal.
*/
class ClassesExtractorCommands extends DrushCommands {
/**
* Create a simple text file via Drush.
*
* @command class_extractor:create
* @aliases cec
*/
public function createFile() {
$config = \Drupal::config('classes_extractor.configform');
$class_extractor_manager = \Drupal::service("classes_extractor.manager");
$classes = $class_extractor_manager->getClasses();
$file_path = $config->get('file_path');
file_put_contents($file_path, implode(' ', array_unique(array_filter($classes))));
}
}
<?php
namespace Drupal\classes_extractor\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Configuration Form Of Class Extractor Module.
*/
class ClassesExtractorConfigForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'classes_extractor.configform',
];
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'classes_extractor_config_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('classes_extractor.configform');
$form['file_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Classes Extractor File Path'),
'#description' => $this->t('Specify the file path to add classes to it'),
'#field_prefix' => DRUPAL_ROOT . '/',
'#max_length' => 255,
'#default_value' => $config->get('file_path'),
'#required' => TRUE,
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
$this->config('classes_extractor.configform')
->set('file_path', $form_state->getValue('file_path'))
->save();
}
/**
* Title of Form.
*/
public function getTitle() {
return t('Classes Extractor Config Form');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment