utilikit-1.0.0/src/Service/UtilikitTestCssGenerator.php
src/Service/UtilikitTestCssGenerator.php
<?php
declare(strict_types=1);
namespace Drupal\utilikit\Service;
use Drupal\utilikit_test\Service\TestGenerator;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\File\FileExists;
/**
* Generates comprehensive test CSS files using all possible utility classes.
*
* This service creates complete CSS files containing all available UtiliKit
* utility classes for testing, development, and validation purposes. It
* leverages the test module's class generator to produce comprehensive CSS
* that can be used to:
* - Test CSS generation performance with large class sets
* - Validate CSS output across all utility patterns
* - Provide complete CSS files for external testing tools
* - Debug CSS generation issues with specific class combinations.
*
* The service requires the utilikit_test module to be enabled as it depends
* on the TestGenerator service to enumerate all possible utility classes.
*/
class UtilikitTestCssGenerator {
/**
* The CSS generator service.
*
* @var \Drupal\utilikit\Service\UtilikitCssGenerator
*/
protected UtilikitCssGenerator $cssGenerator;
/**
* The file manager service.
*
* @var \Drupal\utilikit\Service\UtilikitFileManager
*/
protected UtilikitFileManager $fileManager;
/**
* The file system service.
*
* @var \Drupal\Core\File\FileSystemInterface
*/
protected FileSystemInterface $fileSystem;
/**
* The file URL generator service.
*
* @var \Drupal\Core\File\FileUrlGeneratorInterface
*/
protected FileUrlGeneratorInterface $fileUrlGenerator;
/**
* The test generator service (optional dependency).
*
* @var \Drupal\utilikit_test\Service\TestGenerator|null
*/
protected ?TestGenerator $testGenerator;
/**
* Constructs a new UtilikitTestCssGenerator.
*
* @param \Drupal\utilikit\Service\UtilikitCssGenerator $cssGenerator
* The CSS generator service for creating CSS from utility classes.
* @param \Drupal\utilikit\Service\UtilikitFileManager $fileManager
* The file manager service for handling file operations.
* @param \Drupal\Core\File\FileSystemInterface $fileSystem
* The file system service for directory and file operations.
* @param \Drupal\Core\File\FileUrlGeneratorInterface $fileUrlGenerator
* The file URL generator service for creating accessible URLs.
* @param \Drupal\utilikit_test\Service\TestGenerator|null $testGenerator
* The test generator service for enumerating utility classes. Will be
* NULL if the utilikit_test module is not enabled.
*/
public function __construct(
UtilikitCssGenerator $cssGenerator,
UtilikitFileManager $fileManager,
FileSystemInterface $fileSystem,
FileUrlGeneratorInterface $fileUrlGenerator,
?TestGenerator $testGenerator = NULL,
) {
$this->cssGenerator = $cssGenerator;
$this->fileManager = $fileManager;
$this->fileSystem = $fileSystem;
$this->fileUrlGenerator = $fileUrlGenerator;
$this->testGenerator = $testGenerator;
}
/**
* Generates a complete test CSS file with all possible utility classes.
*
* This method creates a comprehensive CSS file containing all utility
* classes that can be generated by UtiliKit. The process includes:
* - Verifying the test module is available
* - Retrieving all possible utility classes from the test generator
* - Generating complete CSS using the standard CSS generator
* - Creating the necessary directory structure
* - Saving the CSS file with proper permissions
* - Generating an accessible URL for the resulting file.
*
* The generated file is saved as 'utilikit-test-complete.css' in the
* standard UtiliKit CSS directory and can be used for testing, debugging,
* or external validation of CSS generation.
*
* @return array
* An associative array containing the operation result:
* - 'success': (bool) TRUE if CSS generation succeeded, FALSE otherwise
* - 'error': (string) Error message if success is FALSE
* - 'count': (int) Number of utility classes included (success only)
* - 'size': (int) Size of generated CSS in bytes (success only)
* - 'file_url': (string) Absolute URL to the generated file (success only)
*
* @throws \Exception
* If file system operations fail unexpectedly. Exceptions are caught
* and returned as error messages in the result array.
*/
public function generateCompleteTestCss(): array {
// Check if test module is enabled.
if (!$this->testGenerator) {
return [
'success' => FALSE,
'error' => 'Enable utilikit_test module to generate test CSS.',
];
}
// Get all possible classes from existing test generator.
$allClasses = $this->testGenerator->getAllPossibleClasses();
// Validate we have classes.
if (empty($allClasses)) {
return [
'success' => FALSE,
'error' => 'No test classes generated.',
];
}
// Use existing CSS generator.
$css = $this->cssGenerator->generateCssFromClasses($allClasses);
// Save using the file system directly with proper preparation.
try {
$directory = UtilikitConstants::CSS_DIRECTORY;
$filename = 'utilikit-test-complete.css';
$filepath = $directory . '/' . $filename;
// Use injected file system service instead of \Drupal::service.
if (!$this->fileSystem->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS)) {
return [
'success' => FALSE,
'error' => 'Failed to prepare directory.',
];
}
// Save the file using FileExists::Replace like the rest of the module.
$result = $this->fileSystem->saveData($css, $filepath, FileExists::Replace);
if ($result === FALSE) {
return [
'success' => FALSE,
'error' => 'Failed to save CSS file.',
];
}
// Generate URL using the injected service.
$url = $this->fileUrlGenerator->generateAbsoluteString($filepath);
return [
'success' => TRUE,
'count' => count($allClasses),
'size' => strlen($css),
'file_url' => $url,
];
}
catch (\Exception $e) {
return [
'success' => FALSE,
'error' => $e->getMessage(),
];
}
}
/**
* Generates and returns all possible utility classes.
*
* This method retrieves all possible utility classes from the test
* generator without generating CSS. Useful for enumerating classes
* for external tools or validation.
*
* @return array
* Array of all possible utility class names, or empty array if
* test generator is not available.
*/
public function generateAllUtilityClasses(): array {
// Check if test module is enabled.
if (!$this->testGenerator) {
return [];
}
// Get all possible classes from test generator.
return $this->testGenerator->getAllPossibleClasses();
}
/**
* Deletes the test CSS file.
*
* Removes the generated test CSS file from the file system. This is
* useful for cleanup operations, testing, or when regenerating the
* test CSS file.
*
* @return bool
* TRUE if file was deleted successfully or doesn't exist,
* FALSE if deletion failed.
*/
public function deleteTestCssFile(): bool {
$directory = UtilikitConstants::CSS_DIRECTORY;
$filename = 'utilikit-test-complete.css';
$filepath = $directory . '/' . $filename;
// If file doesn't exist, consider it a success.
if (!file_exists($filepath)) {
return TRUE;
}
try {
return $this->fileSystem->delete($filepath);
}
catch (\Exception $e) {
return FALSE;
}
}
/**
* Gets information about the test CSS file.
*
* Returns metadata about the generated test CSS file including
* existence, size, URL, and modification time.
*
* @return array
* An associative array with file information:
* - 'exists': (bool) Whether the file exists
* - 'size': (int|null) File size in bytes, NULL if file doesn't exist
* - 'url': (string|null) Public URL to the file, NULL if doesn't exist
* - 'modified': (int|null) Unix timestamp of last modification,
* NULL if file doesn't exist.
*/
public function getTestCssFileInfo(): array {
$directory = UtilikitConstants::CSS_DIRECTORY;
$filename = 'utilikit-test-complete.css';
$filepath = $directory . '/' . $filename;
// Check if file exists.
if (!file_exists($filepath)) {
return [
'exists' => FALSE,
'size' => NULL,
'url' => NULL,
'modified' => NULL,
];
}
// Get file information.
$realpath = $this->fileSystem->realpath($filepath);
return [
'exists' => TRUE,
'size' => filesize($realpath),
'url' => $this->fileUrlGenerator->generateAbsoluteString($filepath),
'modified' => filemtime($realpath),
];
}
}
