Skip to content
Snippets Groups Projects
Commit 87d0c152 authored by mrweiner's avatar mrweiner
Browse files

Initial commit.

parents
No related branches found
No related tags found
No related merge requests found
{
"name": "drupal/enum_generator",
"type": "drupal-module",
"description": "Enum Generator provides a means of generating enums and class constants files from a Drupal site's entities.",
"homepage": "http://drupal.org/project/enum_generator",
"license": "GPL-2.0+",
"require": {
"nette/php-generator": "^3",
"codeartery/string-utils": "dev-master"
},
"minimum-stability": "dev"
}
name: HC Enum Generator
type: module
description: Helps to generate enum files
package: Custom
core: 8.x
core_version_requirement: ^8 || ^9
dependencies:
- taxonomy
<?php
/**
* @file
* Primary module hooks for HC Enum Generator module.
*
* @DCG
* This file is no longer required in Drupal 8.
* @see https://www.drupal.org/node/2217931
*/
access enum generator:
title: 'Access enum generator routes'
restrict access: true
hc_enum_generator.generator.taxonomy:
path: '/hc-enum-generator/generator/taxonomy'
defaults:
_title: 'Taxonomy generator'
_form: 'Drupal\hc_enum_generator\Form\TaxonomyGeneratorForm'
requirements:
_permission: 'access enum generator'
<?php
namespace Drupal\enum_generator\Form;
use CodeArtery\String\StrTo;
use Drupal;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\taxonomy\TermInterface;
use Nette\PhpGenerator\ClassType;
use Nette\PhpGenerator\PhpFile;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Throwable;
/**
* Provides an enum generator form..
*/
class TaxonomyGeneratorForm extends FormBase {
/**
* The 'const' generation type.
*/
private const TYPE_CONST = 'const';
/**
* The 'enum' generation type.
*/
private const TYPE_ENUM = 'enum';
/**
* The 'string' cast to type.
*/
private const CAST_TO_STRING = 'string';
/**
* The 'int' cast to type.
*/
private const CAST_TO_INT = 'int';
/**
* @var \Drupal\Core\Entity\EntityTypeManager
* The entity type manager.
*/
private EntityTypeManager $entityTypeManager;
/**
* {@inheritDoc}
*/
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->entityTypeManager = $container->get('entity_type.manager');
return $instance;
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'enum_generator_taxonomy_generator';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['desc'] = [
'#markup' => "<strong>Note: </strong>You'll need to reload the page after submitting the form to generate another file.</br></br>",
];
$v_storage = $this->entityTypeManager->getStorage('taxonomy_vocabulary');
/** @var \Drupal\taxonomy\Entity\Vocabulary[] $vocabs */
$vocabs = $v_storage->loadMultiple();
$vocab_opts = [];
foreach ($vocabs as $vocab) {
$vocab_opts[$vocab->id()] = $vocab->label();
}
$form['namespace'] = [
'#type' => 'textfield',
'#title' => $this->t('Namespace'),
'#required' => TRUE,
'#description' => t("The namespace to use for the Enum. This should not be a fully qualified namespace, i.e. it should not start with a backslash."),
'#default_value' => 'Drupal\my_module\Enum',
];
$form['vocab'] = [
'#type' => 'select',
'#title' => $this->t('Vocabulary'),
'#required' => TRUE,
'#options' => $vocab_opts,
'#description' => t("The taxonomy vocabulary for which you'd like to generate an Enum file."),
];
$form['generation_type'] = [
'#title' => $this->t('Generation Type'),
'#type' => 'radios',
'#options' => [
self::TYPE_ENUM => 'Enumerations',
self::TYPE_CONST => 'Class constants',
],
'#description' => $this->t('Whether the generated file should use enumerations or class constants.'),
'#default_value' => self::TYPE_ENUM,
];
$form['cast_to'] = [
'#title' => $this->t('Backing Type'),
'#type' => 'radios',
'#options' => [
self::CAST_TO_STRING => 'Strings',
self::CAST_TO_INT => 'Integers',
],
'#default_value' => self::CAST_TO_STRING,
'#description' => $this->t('The type to use for the Enum backing. Drupal IDs are stored as strings, but will be cast to integers if selected.'),
'#required' => TRUE,
];
$form['actions'] = [
'#type' => 'actions',
];
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Generate'),
];
return $form;
}
/**
* {@inheritDoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$vid = $form_state->getValue('vocab');
$term_storage = $this->entityTypeManager->getStorage('taxonomy_term');
$terms = $term_storage->loadByProperties(['vid' => $vid]);
$vocab = $this->entityTypeManager->getStorage('taxonomy_vocabulary')->load($vid);
usort($terms, function (TermInterface $a, TermInterface $b) {
if ($a->label() < $b->label()) {
return -1;
}
if ($a->label() > $b->label()) {
return 1;
}
return 0;
});
try {
$gen_type = $form_state->getValue('generation_type');
$obj_name = StrTo::studly("{$vocab->label()}Term");
$object = $gen_type === self::TYPE_ENUM
? ClassType::enum($obj_name)
: new ClassType($obj_name);
$type_str = $gen_type === self::TYPE_ENUM ? 'enums' : 'class constants';
$object->addComment("Defines $type_str for terms in the {$vocab->label()} taxonomy.");
foreach ($terms as $term) {
$id = $term->id();
$cast_to = $form_state->getValue('cast_to');
$id_casted = $cast_to === self::CAST_TO_INT ? (int) $id : (string) $id;
$case_name_raw = strtoupper(StrTo::snake($term->label()));
$case_name = is_numeric($case_name_raw[0]) ? "_$case_name_raw" : $case_name_raw;
$object->{$gen_type === self::TYPE_ENUM ? 'addCase' : 'addConstant'}($case_name, $id_casted)
->addComment("Represents the \"{$term->label()}\" term.");
}
// Nette\PhpGenerator provides namespacing but not exactly sure
// how to make it work correctly. Simpler to just insert it
// as a string.
$namespace = $form_state->getValue('namespace');
if (strpos($namespace, '\\') === 0) {
$form_state->setErrorByName('namespace', "Namespace should not start with a backslash.");
return;
}
$file = PhpFile::fromCode("<?php namespace $namespace; {$object->__toString()}");
$form_state->set('filename', "$obj_name.php");
$form_state->set('file_contents', $file->__toString());
}
catch (Throwable $e) {
$form_state->setErrorByName('vocab', "Error generating file: {$e->getMessage()}");
return;
}
}
/**
* {@inheritDoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$filename = $form_state->get('filename');
$file_system = Drupal::service('file_system');
$filepath = $file_system->saveData($form_state->get('file_contents'), "temporary://$filename", FileSystemInterface::EXISTS_REPLACE);
$headers = [
'Content-Type' => 'text/plain',
'Content-Description' => 'File Download',
'Content-Disposition' => 'attachment; filename=' . $filename,
];
$form_state->setResponse(new BinaryFileResponse($filepath, 200, $headers, FALSE));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment