<commit_before><?php
/**
 * This file is part of the Loops framework.
 *
 * @author Lukas <<EMAIL>>
 * @license https://raw.githubusercontent.com/loopsframework/base/master/LICENSE
 * @link https://github.com/loopsframework/base
 * @link https://loopsframework.com/
 * @version 0.1
 */

namespace Loops\Doctrine;

use ArrayAccess;
use ReflectionClass;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Loops;
use Loops\Exception;
use Loops\Form;
use Loops\Annotations\Listen;
use Loops\Form\Element\DoctrineEntitySelect;
use Loops\Form\Element\Text;
use Loops\Form\Element\TextArea;
use Loops\Form\Element\Number;
use Loops\Form\Element\Validator\NotNull;
use Loops\Form\Element\Validator\Length;

/**
 * An intermediate class that automatically sets up missing data of form elements by
 * analyzing doctrine metadata
 */
class EntityForm extends Form {
    public function __construct(ArrayAccess $entity = NULL, $filter = "", $fields = TRUE, $context = NULL, Loops $loops = NULL) {
        parent::__construct($entity, $filter, $context, $loops);

        self::enhanceFromEntity($this, $entity, $filter, $fields, $this->getLoops());
    }
    
    /**
     * @Listen("Session\onInit")
     */
    public function initDoctrineService($value) {
        //make sure doctrines proxy autoloader is ready
        $doctrine = $this->getLoops()->getService("doctrine");
    }

    public static function enhanceFromEntity(Form $form, $entity, $filter = "", $fields = TRUE, Loops $loops = NULL) {
        if(!$loops) {
            $loops = Loops::getCurrentLoops();
        }
        
        //get metadata from doctrine
        $classname = EntityList::getEntityClassname($entity, $loops);
        
        if(!is_object($entity)) {
            $entity = $classname;
        }
        
        $properties = $loops->getService("annotations")->get($classname)->properties;

        $metadata = $loops->getService("doctrine")->getMetadataFactory()->getMetadataFor($classname);

        //find elements
        $elements = $form->getFormElements();

        //add missing fields that are requested and have metadata
        if($fields === TRUE) {
            $missing_fields = array_diff(array_keys($metadata->fieldMappings), array_keys($elements));
        }
        else {
            $missing_fields = array_intersect(array_diff((array)$fields, array_keys($elements)), array_keys($metadata->fieldMappings));
        }
        
        foreach($missing_fields as $name) {
            if(!empty($metadata->fieldMappings[$name]['id'])) {
                continue;
            }

            $elements[$name] = self::addMissingElement($form, $entity, $loops, $name, $metadata->fieldMappings[$name], $properties->$name, $filter, FALSE);
            
            if(!$form->value->offsetExists($name)) {
                $form->value->offsetSet($name, $elements[$name]->getValue());
            }
        }
        
        //add missing accociations
        $missing_assoc = array_intersect(array_diff((array)$fields, array_keys($elements)), array_keys($metadata->associationMappings));
        
        foreach($missing_assoc as $name) {
            $elements[$name] = self::addMissingElement($form, $entity, $loops, $name, $metadata->associationMappings[$name], $properties->$name, $filter, TRUE);
            
            if(!$form->value->offsetExists($name)) {<commit_msg>[Add] Exception if a requested Doctrine Entity element is not available<commit_after><?php
/**
 * This file is part of the Loops framework.
 *
 * @author Lukas <<EMAIL>>
 * @license https://raw.githubusercontent.com/loopsframework/base/master/LICENSE
 * @link https://github.com/loopsframework/base
 * @link https://loopsframework.com/
 * @version 0.1
 */

namespace Loops\Doctrine;

use ArrayAccess;
use ReflectionClass;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Loops;
use Loops\Exception;
use Loops\Form;
use Loops\Annotations\Listen;
use Loops\Form\Element\DoctrineEntitySelect;
use Loops\Form\Element\Text;
use Loops\Form\Element\TextArea;
use Loops\Form\Element\Number;
use Loops\Form\Element\Validator\NotNull;
use Loops\Form\Element\Validator\Length;

/**
 * An intermediate class that automatically sets up missing data of form elements by
 * analyzing doctrine metadata
 */
class EntityForm extends Form {
    public function __construct(ArrayAccess $entity = NULL, $filter = "", $fields = TRUE, $context = NULL, Loops $loops = NULL) {
        parent::__construct($entity, $filter, $context, $loops);

        self::enhanceFromEntity($this, $entity, $filter, $fields, $this->getLoops());
    }
    
    /**
     * @Listen("Session\onInit")
     */
    public function initDoctrineService($value) {
        //make sure doctrines proxy autoloader is ready
        $doctrine = $this->getLoops()->getService("doctrine");
    }

    public static function enhanceFromEntity(Form $form, $entity, $filter = "", $fields = TRUE, Loops $loops = NULL) {
        if(!$loops) {
            $loops = Loops::getCurrentLoops();
        }
        
        //get metadata from doctrine
        $classname = EntityList::getEntityClassname($entity, $loops);
        
        if(!is_object($entity)) {
            $entity = $classname;
        }
        
        $properties = $loops->getService("annotations")->get($classname)->properties;

        $metadata = $loops->getService("doctrine")->getMetadataFactory()->getMetadataFor($classname);

        //find elements
        $elements = $form->getFormElements();

        //add missing fields that are requested and have metadata
        if($fields === TRUE) {
            $missing_fields = array_diff(array_keys($metadata->fieldMappings), array_keys($elements));
        }
        else {
            $missing_fields = array_intersect(array_diff((array)$fields, array_keys($elements)), array_keys($metadata->fieldMappings));
        }
        
        foreach($missing_fields as $name) {
            if(!empty($metadata->fieldMappings[$name]['id'])) {
                continue;
            }

            if(!$entity->offsetExists($name)) {
                $classname = get_class($entity);
                throw new Exception("Failed to create Element for Entity '$classname'. Property '$name' is not accessible.");
            }

            $elements[$name] = self::addMissingElement($form, $entity, $loops, $name, $metadata->fieldMappings[$name], $properties->$name, $filter, FALSE);
            
            if(!$form->value->offsetExists($name)) {
                $form->value->offsetSet($name, $elements[$name]->getValue());
            }
        }
        
        //add missing accociations
        $missing_assoc = array_intersect(array_diff((array)$fields, array_keys($elements)), array_keys($metadata->associationMappings));
        
        foreach($missing_assoc as $name) {
            $elements[$name] = self::addMissingElement($form, $entity, $loops, $name, $metadata->associationMappings[$name], $properties->$name, $filter, TRUE);
            
            if(!$form->value->offsetExists($name)) {
{'fraction_non_alphanumeric': 0.1426131511528608, 'fraction_numerical': 0.000569313976658127, 'mean_word_length': 2.9858196256381166, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 58, 'https://': 6, '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': '6625754', 'n_tokens_mistral': 1981, 'n_tokens_neox': 1954, 'n_words': 411}