<commit_before><?php

namespace Kunstmaan\GeneratorBundle\Generator;

use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
use Doctrine\ORM\Tools\EntityGenerator;
use Kunstmaan\GeneratorBundle\Helper\GeneratorUtils;
use Sensio\Bundle\GeneratorBundle\Generator\Generator;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\Yaml\Yaml;

/**
 * Generates all classes/files for a new pagepart
 */
class PagePartGenerator extends Generator
{

    /**
     * @var Filesystem
     */
    private $filesystem;

    /**
     * @var RegistryInterface
     */
    private $registry;

    /**
     * @var string
     */
    private $skeletonDir;

    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * @var BundleInterface
     */
    private $bundle;

    /**
     * @var string
     */
    private $entity;

    /**
     * @var string
     */
    private $prefix;

    /**
     * @var array
     */
    private $fields;

    /**
     * @var array
     */
    private $sections;

    /**
     * @param Filesystem        $filesystem  The filesystem
     * @param RegistryInterface $registry    The registry
     * @param string            $skeletonDir The directory of the skeleton
     * @param OutputInterface   $output      The output
     */
    public function __construct(Filesystem $filesystem, RegistryInterface $registry, $skeletonDir, OutputInterface $output)
    {
        $this->filesystem = $filesystem;
        $this->registry = $registry;
        $this->skeletonDir = GeneratorUtils::getFullSkeletonPath($skeletonDir);
        $this->output = $output;

        $this->setSkeletonDirs(array($this->skeletonDir));
    }

    /**
     * Generate the pagepart.
     *
     * @param BundleInterface $bundle         The bundle
     * @param string          $entity         The entity name
     * @param string          $prefix         The database prefix
     * @param array           $fields         The fields
     * @param array           $sections       The page sections
     *
     * @throws \RuntimeException
     */
    public function generate(BundleInterface $bundle, $entity, $prefix, array $fields, array $sections)
    {
        $this->bundle = $bundle;
        $this->entity = $entity;
        $this->prefix = $prefix;
        $this->fields = $fields;
        $this->sections = $sections;

        $this->generateEntity();
        $this->generateFormType();
        $this->generateResourceTemplate();
        $this->generateSectionConfig();
    }

    /**
     * Generate the pagepart entity.
     *
     * @throws \RuntimeException
     */
    private function generateEntity()
    {
        // configure the bundle (needed if the bundle does not contain any Entities yet)
        $config = $this->registry->getEntityManager(null)->getConfiguration();
        $config->setEntityNamespaces(array_merge(
            array($this->bundle->getName() => $this->bundle->getNamespace().'\\Entity\\PageParts'),
            $config->getEntityNamespaces()
        ));

        $entityClass = $this->registry->getEntityNamespace($this->bundle->getName()).'\\PageParts\\'.$this->entity;
        $entityPath = $this->bundle->getPath().'/Entity/PageParts/'.str_replace('\\', '/', $this->entity).'.php';
        if (file_exists($entityPath)) {
            throw new \RuntimeException(sprintf('Entity "%s" already exists.', $entityClass));
        }

        $class = new ClassMetadataInfo($entityClass, new UnderscoreNamingStrategy());
        foreach ($this->fields as $fieldSet) {
            foreach ($fieldSet as $fieldArray) {
                foreach ($fieldArray as $field) {
                    if (array_key_exists('joinColumn', $field)) {
                        $class->mapManyToOne($field);
                    } elseif (array_key_exists('joinTable', $field)) {
                        $class->mapManyToMany($field);
                    } else {
                        $class->mapField($field);
                    }
                }
            }
        }
        if (!is_null($this->prefix)) {
            $class->setPrimaryTable(array('name' => strtolower($this->prefix.'__'.strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $this->entity)))));
        } else {
            list($project, $bundle) = explode("\\", $this->bundle->getNameSpace());
            $class->setPrimaryTable(array('name' => strtolower($project.'__'.strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $this->entity)))));
        }
        $entityCode = $this->getEntityGenerator()->generateEntityClass($class);

        // Add some extra functions in the generated entity :s
        $params = array(
            'bundle' => $this->bundle->getName(),
            'pagepart' => $this->entity,
            'adminType' => '\\'.$this->bundle->getNamespace().'\\Form\\PageParts\\'.$this->entity.'AdminType'
        );
        $extraCode = $this->render('/Entity/PageParts/ExtraFunctions.php', $params);

        $pos = strrpos($entityCode, "}");
        $trimmed = substr($entityCode, 0, $pos);
        $entityCode = $trimmed."\n".$extraCode."\n}";

        $this->filesystem->mkdir(dirname($entityPath));
        file_put_contents($entityPath, $entityCode);

        $this->output->writeln('Generating entity : <info>OK</info>');
    }

    /**
     * Generate the admin form type entity.
     */
    private function generateFormType()
    {
        $className = $this->entity.'AdminType';
        $savePath = $this->bundle->getPath().'/Form/PageParts/'.$className.'.php';
        $name = str_replace("\\", '_', strtolower($this->bundle->getNamespace())).'_'.strtolower($this->entity).'type';

        $params = array(
            'className' => $className,
            'name' => $name,
            'namespace' => $this->bundle->getNamespace(),
            'entity' => '\\'.$this->bundle->getNamespace().'\Entity\\PageParts\\'.$this->entity,
            'fields' => $this->fields
        );
        $this->renderFile('/Form/PageParts/AdminType.php', $savePath, $params);

        $this->output->writeln('Generating form type : <info>OK</info>');
    }

    /**
     * Generate the twig template.
     */
    private function generateResourceTemplate()
    {
        $savePath = $this->bundle->getPath().'/Resources/views/PageParts/'.$this->entity.'/view.html.twig';

        $params = array(
            'pagepart' => $this->entity,
            'fields' => $this->fields
        );
        $this->renderFile('/Resources/views/PageParts/view.html.twig', $savePath, $params);

        $this->output->writeln('Generating template : <info>OK</info>');
    }

    /**
     * Update the page section config files
     */
    private function generateSectionConfig()
    {
        if (count($this->sections) > 0) {<commit_msg>css naming convention<commit_after><?php

namespace Kunstmaan\GeneratorBundle\Generator;

use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
use Doctrine\ORM\Tools\EntityGenerator;
use Kunstmaan\GeneratorBundle\Helper\GeneratorUtils;
use Sensio\Bundle\GeneratorBundle\Generator\Generator;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\Yaml\Yaml;

/**
 * Generates all classes/files for a new pagepart
 */
class PagePartGenerator extends Generator
{

    /**
     * @var Filesystem
     */
    private $filesystem;

    /**
     * @var RegistryInterface
     */
    private $registry;

    /**
     * @var string
     */
    private $skeletonDir;

    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * @var BundleInterface
     */
    private $bundle;

    /**
     * @var string
     */
    private $entity;

    /**
     * @var string
     */
    private $prefix;

    /**
     * @var array
     */
    private $fields;

    /**
     * @var array
     */
    private $sections;

    /**
     * @param Filesystem        $filesystem  The filesystem
     * @param RegistryInterface $registry    The registry
     * @param string            $skeletonDir The directory of the skeleton
     * @param OutputInterface   $output      The output
     */
    public function __construct(Filesystem $filesystem, RegistryInterface $registry, $skeletonDir, OutputInterface $output)
    {
        $this->filesystem = $filesystem;
        $this->registry = $registry;
        $this->skeletonDir = GeneratorUtils::getFullSkeletonPath($skeletonDir);
        $this->output = $output;

        $this->setSkeletonDirs(array($this->skeletonDir));
    }

    /**
     * Generate the pagepart.
     *
     * @param BundleInterface $bundle         The bundle
     * @param string          $entity         The entity name
     * @param string          $prefix         The database prefix
     * @param array           $fields         The fields
     * @param array           $sections       The page sections
     *
     * @throws \RuntimeException
     */
    public function generate(BundleInterface $bundle, $entity, $prefix, array $fields, array $sections)
    {
        $this->bundle = $bundle;
        $this->entity = $entity;
        $this->prefix = $prefix;
        $this->fields = $fields;
        $this->sections = $sections;

        $this->generateEntity();
        $this->generateFormType();
        $this->generateResourceTemplate();
        $this->generateSectionConfig();
    }

    /**
     * Generate the pagepart entity.
     *
     * @throws \RuntimeException
     */
    private function generateEntity()
    {
        // configure the bundle (needed if the bundle does not contain any Entities yet)
        $config = $this->registry->getEntityManager(null)->getConfiguration();
        $config->setEntityNamespaces(array_merge(
            array($this->bundle->getName() => $this->bundle->getNamespace().'\\Entity\\PageParts'),
            $config->getEntityNamespaces()
        ));

        $entityClass = $this->registry->getEntityNamespace($this->bundle->getName()).'\\PageParts\\'.$this->entity;
        $entityPath = $this->bundle->getPath().'/Entity/PageParts/'.str_replace('\\', '/', $this->entity).'.php';
        if (file_exists($entityPath)) {
            throw new \RuntimeException(sprintf('Entity "%s" already exists.', $entityClass));
        }

        $class = new ClassMetadataInfo($entityClass, new UnderscoreNamingStrategy());
        foreach ($this->fields as $fieldSet) {
            foreach ($fieldSet as $fieldArray) {
                foreach ($fieldArray as $field) {
                    if (array_key_exists('joinColumn', $field)) {
                        $class->mapManyToOne($field);
                    } elseif (array_key_exists('joinTable', $field)) {
                        $class->mapManyToMany($field);
                    } else {
                        $class->mapField($field);
                    }
                }
            }
        }
        if (!is_null($this->prefix)) {
            $class->setPrimaryTable(array('name' => strtolower($this->prefix.'__'.strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $this->entity)))));
        } else {
            list($project, $bundle) = explode("\\", $this->bundle->getNameSpace());
            $class->setPrimaryTable(array('name' => strtolower($project.'__'.strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $this->entity)))));
        }
        $entityCode = $this->getEntityGenerator()->generateEntityClass($class);

        // Add some extra functions in the generated entity :s
        $params = array(
            'bundle' => $this->bundle->getName(),
            'pagepart' => $this->entity,
            'adminType' => '\\'.$this->bundle->getNamespace().'\\Form\\PageParts\\'.$this->entity.'AdminType'
        );
        $extraCode = $this->render('/Entity/PageParts/ExtraFunctions.php', $params);

        $pos = strrpos($entityCode, "}");
        $trimmed = substr($entityCode, 0, $pos);
        $entityCode = $trimmed."\n".$extraCode."\n}";

        $this->filesystem->mkdir(dirname($entityPath));
        file_put_contents($entityPath, $entityCode);

        $this->output->writeln('Generating entity : <info>OK</info>');
    }

    /**
     * Generate the admin form type entity.
     */
    private function generateFormType()
    {
        $className = $this->entity.'AdminType';
        $savePath = $this->bundle->getPath().'/Form/PageParts/'.$className.'.php';
        $name = str_replace("\\", '_', strtolower($this->bundle->getNamespace())).'_'.strtolower($this->entity).'type';

        $params = array(
            'className' => $className,
            'name' => $name,
            'namespace' => $this->bundle->getNamespace(),
            'entity' => '\\'.$this->bundle->getNamespace().'\Entity\\PageParts\\'.$this->entity,
            'fields' => $this->fields
        );
        $this->renderFile('/Form/PageParts/AdminType.php', $savePath, $params);

        $this->output->writeln('Generating form type : <info>OK</info>');
    }

    /**
     * Generate the twig template.
     */
    private function generateResourceTemplate()
    {
        $savePath = $this->bundle->getPath().'/Resources/views/PageParts/'.$this->entity.'/view.html.twig';

        $params = array(
            'pagepart' => strtolower(preg_replace('/([a-z])([A-Z])/', '$1-$2', $this->entity)),
            'fields' => $this->fields
        );
        $this->renderFile('/Resources/views/PageParts/view.html.twig', $savePath, $params);

        $this->output->writeln('Generating template : <info>OK</info>');
    }

    /**
     * Update the page section config files
     */
    private function generateSectionConfig()
    {
        if (count($this->sections) > 0) {
{'fraction_non_alphanumeric': 0.15870172673210575, 'fraction_numerical': 0.0010030808913090205, 'mean_word_length': 2.3249166269652215, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 205, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3749050', 'n_tokens_mistral': 3962, 'n_tokens_neox': 3888, 'n_words': 716}