<commit_before><?php

class CM_Config_Generator extends CM_Class_Abstract {

    private $_typesMaxValue = 0;

    /** @var string[] */
    private $_classTypes = array();

    /** @var string[][] */
    private $_namespaceTypes = array();

    /**
     * @throws CM_Exception_Invalid
     * @return array[]
     */
    public function getNamespaceTypes() {
        if (empty($this->_namespaceTypes)) {
            throw new CM_Exception_Invalid('Class Types have not been generated.');
        }
        return $this->_namespaceTypes;
    }

    /**
     * @return string[]
     * @throws CM_Exception_Invalid
     */
    public function getClassTypes() {
        if (empty($this->_classTypes)) {
            throw new CM_Exception_Invalid('Class Types have not been generated.');
        }
        return $this->_classTypes;
    }

    public function generateClassTypes() {
        $config = CM_Config::get();
        if (isset(CM_Config::get()->CM_Class_Abstract->typesMaxValue)) {
            $this->_typesMaxValue = CM_Config::get()->CM_Class_Abstract->typesMaxValue;
        }
        $typedClasses = CM_Util::getClassChildren('CM_Typed', true);
        /** @var CM_Class_Abstract[] $namespaceClassList */
        $namespaceClassList = array();
        // fetch type-namespaces
        foreach ($typedClasses as $class) {
            if (!is_subclass_of(get_parent_class($class), 'CM_Typed')) {
                $namespaceClassList[] = $class;
            }
        }
        // fetch current types
        foreach ($namespaceClassList as $namespaceClass) {
            if (isset($config->$namespaceClass->types)) {
                foreach ($config->$namespaceClass->types as $type => $class) {
                    if ($classNameDuplicate = array_search($type, $this->_classTypes)) {
                        throw new CM_Exception_Invalid(
                            'Duplicate `TYPE` constant for `' . $class . '` and `' . $classNameDuplicate . '`. Both equal `' . $type . '`.');
                    }
                    $this->_classTypes[$type] = $class;
                }
            }
        }
        // generate new types
        foreach ($namespaceClassList as $namespaceClass) {
            $this->_namespaceTypes[$namespaceClass] = array();
            $containedClasses = $namespaceClass::getClassChildren();
            $reflectionClass = new ReflectionClass($namespaceClass);
            if (!$reflectionClass->isAbstract()) {
                array_unshift($containedClasses, $namespaceClass);
            }
            foreach ($containedClasses as $class) {
                if (false === $type = array_search($class, $this->_classTypes)) {
                    $type = ++$this->_typesMaxValue;
                    $this->_classTypes[$type] = $class;
                }
                $this->_namespaceTypes[$namespaceClass][$type] = $class;
            }<commit_msg>check if class exists before adopting old configuration<commit_after><?php

class CM_Config_Generator extends CM_Class_Abstract {

    private $_typesMaxValue = 0;

    /** @var string[] */
    private $_classTypes = array();

    /** @var string[][] */
    private $_namespaceTypes = array();

    /**
     * @throws CM_Exception_Invalid
     * @return array[]
     */
    public function getNamespaceTypes() {
        if (empty($this->_namespaceTypes)) {
            throw new CM_Exception_Invalid('Class Types have not been generated.');
        }
        return $this->_namespaceTypes;
    }

    /**
     * @return string[]
     * @throws CM_Exception_Invalid
     */
    public function getClassTypes() {
        if (empty($this->_classTypes)) {
            throw new CM_Exception_Invalid('Class Types have not been generated.');
        }
        return $this->_classTypes;
    }

    public function generateClassTypes() {
        $config = CM_Config::get();
        if (isset(CM_Config::get()->CM_Class_Abstract->typesMaxValue)) {
            $this->_typesMaxValue = CM_Config::get()->CM_Class_Abstract->typesMaxValue;
        }
        $typedClasses = CM_Util::getClassChildren('CM_Typed', true);
        /** @var CM_Class_Abstract[] $namespaceClassList */
        $namespaceClassList = array();
        // fetch type-namespaces
        foreach ($typedClasses as $class) {
            if (!is_subclass_of(get_parent_class($class), 'CM_Typed')) {
                $namespaceClassList[] = $class;
            }
        }
        // fetch current types
        foreach ($namespaceClassList as $namespaceClass) {
            if (isset($config->$namespaceClass->types)) {
                foreach ($config->$namespaceClass->types as $type => $class) {
                    if ($classNameDuplicate = array_search($type, $this->_classTypes)) {
                        throw new CM_Exception_Invalid(
                            'Duplicate `TYPE` constant for `' . $class . '` and `' . $classNameDuplicate . '`. Both equal `' . $type . '`.');
                    }
                    if (class_exists($class)) {
                        $this->_classTypes[$type] = $class;
                    }
                }
            }
        }
        // generate new types
        foreach ($namespaceClassList as $namespaceClass) {
            $this->_namespaceTypes[$namespaceClass] = array();
            $containedClasses = $namespaceClass::getClassChildren();
            $reflectionClass = new ReflectionClass($namespaceClass);
            if (!$reflectionClass->isAbstract()) {
                array_unshift($containedClasses, $namespaceClass);
            }
            foreach ($containedClasses as $class) {
                if (false === $type = array_search($class, $this->_classTypes)) {
                    $type = ++$this->_typesMaxValue;
                    $this->_classTypes[$type] = $class;
                }
                $this->_namespaceTypes[$namespaceClass][$type] = $class;
            }
{'fraction_non_alphanumeric': 0.12945368171021376, 'fraction_numerical': 0.00033932813030200206, 'mean_word_length': 2.0045871559633026, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 47, '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': '1984073', 'n_tokens_mistral': 1520, 'n_tokens_neox': 1486, 'n_words': 309}