<commit_before><?php
namespace Hostnet\Component\EntityPlugin;

use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;

/**
 * The generator for stage 2 that only has to hook into composer
 * It generates the combined entity and repository traits
 * Generated/ClientTrait and Generated/ClientRepositoryTrait
 *
 * @author <NAME> <<EMAIL>>
 */
class CompoundGenerator
{

    private $io;

    private $environment;

    private $entity_package;

    private $writer;

    /**
     * @param IOInterface $io
     * @param \Twig_Environment $environment
     * @param EntityPackage $entity_package
     * @param WriterInterface $writer
     */
    public function __construct(
        IOInterface $io,
        \Twig_Environment $environment,
        EntityPackage $entity_package,
        WriterInterface $writer
    ) {
        $this->io             = $io;
        $this->environment    = $environment;
        $this->entity_package = $entity_package;
        $this->writer         = $writer;
    }

    /**
     * Ask the generator to generate all the trait of traits, and their matching combined interfaces
     *
     * @return void
     */
    public function generate()
    {
        foreach ($this->entity_package->getPackageContent()->getEntities() as $package_class) {
            /* @var $package_class PackageClass */

            $this->writeIfDebug(
                '        - Finding traits for <info>' . $package_class->getName() . '</info>.'
            );
            $required_traits = $this->recursivelyFindUseStatementsFor($this->entity_package, $package_class);
            $optional_traits = $this->findUseStatementsForOptionalTraits($this->entity_package, $package_class);
            $traits          = array_merge($required_traits, $optional_traits);

            $this->generateTrait($package_class, $traits);
        }
    }

    private function findUseStatementsForOptionalTraits(
        EntityPackage $entity_package,
        PackageClass $package_class
    ) {
        $content = $entity_package->getPackageContent();
        $traits  = $content->getOptionalEntityTraits($package_class->getShortName());
        $result  = [];

        foreach ($traits as $trait) {
            /* @var $trait OptionalPackageTrait */
            $requirement = $trait->getRequirement();
            if ($content->hasEntity($requirement)) {
                $result[] = $trait;
                $this->writeIfDebug(
                    'Injected <info>' . $trait->getName() .   '</info> from <info>' .
                    $entity_package->getPackage()->getName() .
                    '</info>.'
                );
            } else {
                $this->writeIfDebug(
                    'Not injected <info>' . $trait->getName() .   '</info> from <info>' .
                    $entity_package->getPackage()->getName() . ' because ' . $requirement . 'is not found.</info>.'
                );
            }
        }
        return $result;
    }
    /**
     * Gives all the entities to be required in the compound interface
     * Also generates a unique alias for them
     *
     * @param EntityPackage $entity_package
     * @param string $class_name
     * @param bool $has_recursed Is this the first time this function is called, or is it recursing.
     * @return array[]UseStatement
     */
    private function recursivelyFindUseStatementsFor(
        EntityPackage $entity_package,
        PackageClass $package_class,
        $has_recursed = false
    ) {
        $result = array();
        foreach ($entity_package->getDependentPackages() as $dependent_package) {
            /* @var $package EntityPackage */
            $use_statements = $this->recursivelyFindUseStatementsFor($dependent_package, $package_class, false);
            $result         = array_merge($result, $use_statements);
        }
        $package_class = $entity_package->getPackageContent()->getEntityOrEntityTrait($package_class->getShortName());
        if ($package_class) {
            if ($has_recursed) {
                $this->writeIfDebug(
                    '          Injected <info>' .
                    $package_class->getName() .
                    '</info> from <info>' .
                    $entity_package->getPackage()->getName() .
                    '</info>.'
                );
            }
            $result[] = $package_class;
        } else {
            $this->writeIfDebug('          No trait in <info>' . $entity_package->getPackage()->getName() . '</info>.');
        }

        return $result;
    }

    /**
     * Generates Generated/<class_name>Traits.php
     *
     * @param string $relative_path<commit_msg>Fixed recursion issue with circular dependencies<commit_after><?php
namespace Hostnet\Component\EntityPlugin;

use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;

/**
 * The generator for stage 2 that only has to hook into composer
 * It generates the combined entity and repository traits
 * Generated/ClientTrait and Generated/ClientRepositoryTrait
 *
 * @author <NAME> <<EMAIL>>
 */
class CompoundGenerator
{

    private $io;

    private $environment;

    private $entity_package;

    private $writer;

    /**
     * @param IOInterface $io
     * @param \Twig_Environment $environment
     * @param EntityPackage $entity_package
     * @param WriterInterface $writer
     */
    public function __construct(
        IOInterface $io,
        \Twig_Environment $environment,
        EntityPackage $entity_package,
        WriterInterface $writer
    ) {
        $this->io             = $io;
        $this->environment    = $environment;
        $this->entity_package = $entity_package;
        $this->writer         = $writer;
    }

    /**
     * Ask the generator to generate all the trait of traits, and their matching combined interfaces
     *
     * @return void
     */
    public function generate()
    {
        foreach ($this->entity_package->getPackageContent()->getEntities() as $package_class) {
            /* @var $package_class PackageClass */

            $this->writeIfDebug(
                '        - Finding traits for <info>' . $package_class->getName() . '</info>.'
            );
            $required_traits = $this->recursivelyFindUseStatementsFor($this->entity_package, $package_class);
            $optional_traits = $this->findUseStatementsForOptionalTraits($this->entity_package, $package_class);
            $traits          = array_merge($required_traits, $optional_traits);

            $this->generateTrait($package_class, $traits);
        }
    }

    private function findUseStatementsForOptionalTraits(
        EntityPackage $entity_package,
        PackageClass $package_class
    ) {
        $content = $entity_package->getPackageContent();
        $traits  = $content->getOptionalEntityTraits($package_class->getShortName());
        $result  = [];

        foreach ($traits as $trait) {
            /* @var $trait OptionalPackageTrait */
            $requirement = $trait->getRequirement();
            if ($content->hasEntity($requirement)) {
                $result[] = $trait;
                $this->writeIfDebug(
                    'Injected <info>' . $trait->getName() .   '</info> from <info>' .
                    $entity_package->getPackage()->getName() .
                    '</info>.'
                );
            } else {
                $this->writeIfDebug(
                    'Not injected <info>' . $trait->getName() .   '</info> from <info>' .
                    $entity_package->getPackage()->getName() . ' because ' . $requirement . 'is not found.</info>.'
                );
            }
        }
        return $result;
    }
    /**
     * Gives all the entities to be required in the compound interface
     * Also generates a unique alias for them
     *
     * @param EntityPackage $entity_package
     * @param string $class_name
     * @param array $checked list of checked packages to prevent recusrion errors
     * @return array[]UseStatement
     */
    private function recursivelyFindUseStatementsFor(
        EntityPackage $entity_package,
        PackageClass $package_class,
        array $checked = []
    ) {
        $result = array();
        foreach ($entity_package->getDependentPackages() as $dependent_package) {
            /* @var $package EntityPackage */
            if (!in_array($dependent_package, $checked)) {
                $checked[]      = $dependent_package;
                $use_statements = $this->recursivelyFindUseStatementsFor($dependent_package, $package_class, $checked);
                $result         = array_merge($result, $use_statements);
            }
        }
        $package_class = $entity_package->getPackageContent()->getEntityOrEntityTrait($package_class->getShortName());
        if ($package_class) {
            $result[] = $package_class;
        } else {
            $this->writeIfDebug('          No trait in <info>' . $entity_package->getPackage()->getName() . '</info>.');
        }

        return $result;
    }

    /**
     * Generates Generated/<class_name>Traits.php
     *
     * @param string $relative_path
{'fraction_non_alphanumeric': 0.11746031746031746, 'fraction_numerical': 0.00021893814997263274, 'mean_word_length': 2.1043153244988106, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 113, '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': '6479763', 'n_tokens_mistral': 2424, 'n_tokens_neox': 2351, 'n_words': 531}