<commit_before><?php

namespace Splash\Tests\Tools\Traits;

use Splash\Client\Splash;

/**
 * @abstract    Splash Test Tools - Objects Faker trait
 *
 * @author SplashSync <<EMAIL>>
 */
trait ObjectsFakerTrait
{
    //==============================================================================
    //      FAKE DATA GENERATORS
    //==============================================================================
    
    /**
     *   @abstract   Generate Fake Object Fields List
     *
     *   @param      string     $ObjectType     Object Type Name
     *   @param      array      $FieldsList     Object Field Ids List
     *   @param      bool       $Associate      Include Associated Fields
     *
     *   @return     array      $Out            Array of Fields
     */
    public function fakeFieldsList($ObjectType, $FieldsList = false, $Associate = false)
    {
        //====================================================================//
        // Safety Check => $ObjectType is a valid
        $this->assertTrue(in_array($ObjectType, Splash::objects()), "Invalid Object Type Name. (" . $ObjectType . ")");

        //====================================================================//
        // Create Empty Object Data Array
        $Out    = array();
        
        //====================================================================//
        // Load Object Fields Definition
        $Fields = Splash::object($ObjectType)->fields();
        if (empty($Fields)) {
            return $Out;
        }
        
        //====================================================================//
        // Generate Fields Data
        foreach ($Fields as $Field) {
            //====================================================================//
            // Check if Fields is Needed
            if (!$this->isFieldNeeded($Field, $FieldsList)) {
                continue;
            }
            //====================================================================//
            // Add Fields to List
            $Out[$Field->id] = $Field;
        }
        
        //====================================================================//
        // No Associated Fields
        if (!$Associate) {
            return $Out;
        }
        
        //====================================================================//
        // Add Associated Fields to List
        foreach ($Out as $OutField) {
            //====================================================================//
            // No Associated Field
            if (empty($OutField->asso)) {
                continue;
            }
            //====================================================================//
            // For Associated Fields
            foreach ($Fields as $Field) {
                if (in_array($Field->id, $OutField->asso)) {
                    $Out[$Field->id] = $Field;
                }
            }
        }
        
        return $Out;
    }
    
    /**
     *   @abstract   Check if Field Need to e in List
     *
     *   @param      ArrayObject    $Field          Field Definition
     *   @param      array          $FieldsList     Object Field Ids List
     *
     *   @return     bool
     */
    private function isFieldNeeded($Field, $FieldsList = false)
    {
        //====================================================================//
        // Check if Fields is Writable
        if (!$Field->write) {
            return false;
        }
        //====================================================================//
        // Check if Fields is Needed
        //====================================================================//

        //====================================================================//
        // Required Field
        if ($Field->required) {
            return true;
        }
        //====================================================================//
        // If NO Fields List is Given => Select All Write Fields
        if (($FieldsList == false) || !is_array($FieldsList)) {
            return true;
        }
        //====================================================================//
        // Field is in Requested List
        if (!in_array($Field->id, $FieldsList)) {
            return false;
        }
        return true;
    }
    
    /**
     *   @abstract   Create Fake/Dummy Object Data
     *
     *   @param      array   $FieldsList     Object Field List
     *
     *   @return     int     $result     0 if KO, 1 if OK
     */
    public function fakeObjectData($FieldsList)
    {
        //====================================================================//
        // Create Dummy Data Array
        $Out = array();
        if (empty($FieldsList)) {
            return $Out;
        }
        
        //====================================================================//
        // Create Dummy Fields Data
        foreach ($FieldsList as $Field) {
            //====================================================================//
            // Generate Single Fields Dummy Data (is Not a List Field)
            if (!self::isListField($Field->id)) {
                $Out[$Field->id] = self::fakeFieldData($Field->type, $Field->choices, $Field->options);
                continue;
            }
            
            //====================================================================//
            // Generate Dummy List  Data
            $List       =   self::isListField($Field->id);
            $ListName   =   $List["listname"];
            $FieldName  =   $List["fieldname"];
            $ListData   =   self::fakeListData($Field);
            //====================================================================//
            // Create List
            if (!array_key_exists($ListName, $Out)) {
                $Out[$ListName] = array();
            }
            //====================================================================//
            // Parse Data in List
            foreach ($ListData as $Key => $Data) {
                if (!array_key_exists($Key, $Out[$ListName])) {
                    $Out[$ListName][$Key] = array();
                }
                $Out[$ListName][$Key][$FieldName] = $Data[$FieldName];
            }
        }
        return $Out;
    }
    
    /**
     *   @abstract   Create Fake/Dummy Object List Data
     *
     *   @param      array   $Field          Object Field Definition
     *
     *   @return     int     $result     0 if KO, 1 if OK
     */
    public function fakeListData($Field)
    {
        //====================================================================//
        // Read Number of Items to Put in Lists
        $NbItems =  $this->settings["ListItems"]?$this->settings["ListItems"]:2;
        //====================================================================//
        // Parse List Identifiers
        $List   =   self::isListField($Field->id);
        $Type   =   self::isListField($Field->type);
        
        //====================================================================//
        // Generate Unik Dummy Fields Data
        $ListData = array();
        while (count($ListData) < $NbItems) {
            $Data           =   self::fakeFieldData($Type["fieldname"], $Field->choices, $Field->options);
            $Md5            =   md5(serialize($Data));
            $ListData[$Md5] =   $Data;
        }

        //====================================================================//
        // Create Dummy List Data
        $Out = array();<commit_msg>PhpUnit: Added Data Preserve for Required but Not tested fields between Create & Update<commit_after><?php

namespace Splash\Tests\Tools\Traits;

use Splash\Client\Splash;

/**
 * @abstract    Splash Test Tools - Objects Faker trait
 *
 * @author SplashSync <<EMAIL>>
 */
trait ObjectsFakerTrait
{
    //==============================================================================
    //      FAKE DATA GENERATORS
    //==============================================================================
    
    /**
     *   @abstract   Generate Fake Object Fields List
     *
     *   @param      string     $ObjectType     Object Type Name
     *   @param      array      $FieldsList     Object Field Ids List
     *   @param      bool       $Associate      Include Associated Fields
     *
     *   @return     array      $Out            Array of Fields
     */
    public function fakeFieldsList($ObjectType, $FieldsList = false, $Associate = false)
    {
        //====================================================================//
        // Safety Check => $ObjectType is a valid
        $this->assertTrue(in_array($ObjectType, Splash::objects()), "Invalid Object Type Name. (" . $ObjectType . ")");

        //====================================================================//
        // Create Empty Object Data Array
        $Out    = array();
        
        //====================================================================//
        // Load Object Fields Definition
        $Fields = Splash::object($ObjectType)->fields();
        if (empty($Fields)) {
            return $Out;
        }
        
        //====================================================================//
        // Generate Fields Data
        foreach ($Fields as $Field) {
            //====================================================================//
            // Check if Fields is Needed
            if (!$this->isFieldNeeded($Field, $FieldsList)) {
                continue;
            }
            //====================================================================//
            // Add Fields to List
            $Out[$Field->id] = $Field;
        }
        
        //====================================================================//
        // No Associated Fields
        if (!$Associate) {
            return $Out;
        }
        
        //====================================================================//
        // Add Associated Fields to List
        foreach ($Out as $OutField) {
            //====================================================================//
            // No Associated Field
            if (empty($OutField->asso)) {
                continue;
            }
            //====================================================================//
            // For Associated Fields
            foreach ($Fields as $Field) {
                if (in_array($Field->id, $OutField->asso)) {
                    $Out[$Field->id] = $Field;
                }
            }
        }
        
        return $Out;
    }
    
    /**
     *   @abstract   Check if Field Need to be in List
     *
     *   @param      ArrayObject    $Field          Field Definition
     *   @param      array          $FieldsList     Object Field Ids List
     *
     *   @return     bool
     */
    private function isFieldNeeded($Field, $FieldsList = false)
    {
        //====================================================================//
        // Check if Fields is Writable
        if (!$Field->write) {
            return false;
        }
        //====================================================================//
        // Check if Fields is Needed
        //====================================================================//

        //====================================================================//
        // Required Field
        if ($Field->required) {
            return true;
        }
        //====================================================================//
        // If NO Fields List is Given => Select All Write Fields
        if (($FieldsList == false) || !is_array($FieldsList)) {
            return true;
        }
        //====================================================================//
        // Field is in Requested List
        if (!in_array($Field->id, $FieldsList)) {
            return false;
        }
        return true;
    }
    
    /**
     *   @abstract   Create Fake/Dummy Object Data
     *
     *   @param      array   $FieldsList     Object Field List
     *   @param      array   $OriginData     Original Object Data
     *
     *   @return     int     $result     0 if KO, 1 if OK
     */
    public function fakeObjectData($FieldsList, $OriginData = null)
    {
        //====================================================================//
        // Create Dummy Data Array
        $Out = array();
        if (empty($FieldsList)) {
            return $Out;
        }
        
        //====================================================================//
        // Create Dummy Fields Data
        foreach ($FieldsList as $Field) {
            //====================================================================//
            // Generate Single Fields Dummy Data (is Not a List Field)
            if (!self::isListField($Field->id)) {
                $Out[$Field->id] = (self::isFieldToPreserve($Field, $OriginData) ?
                        $OriginData[$Field->id] :
                        self::fakeFieldData($Field->type, $Field->choices, $Field->options)
                    );
                continue;
            }
            
            //====================================================================//
            // Generate Dummy List  Data
            $List       =   self::isListField($Field->id);
            $ListName   =   $List["listname"];
            $FieldName  =   $List["fieldname"];
            $ListData   =   self::fakeListData($Field);
            //====================================================================//
            // Create List
            if (!array_key_exists($ListName, $Out)) {
                $Out[$ListName] = array();
            }
            //====================================================================//
            // Parse Data in List
            foreach ($ListData as $Key => $Data) {
                if (!array_key_exists($Key, $Out[$ListName])) {
                    $Out[$ListName][$Key] = array();
                }
                $Out[$ListName][$Key][$FieldName] = $Data[$FieldName];
            }
        }
        return $Out;
    }

    /**
     *   @abstract   Check if Field Need to e in List
     *
     *   @param      ArrayObject    $Field          Field Definition
     *   @param      array          $OriginData     Original Object Data
     *
     *   @return     bool
     */
    private static function isFieldToPreserve($Field, $OriginData)
    {
        //====================================================================//
        // Check if Origin Data Exists
        if (empty($OriginData) || !isset($OriginData[$Field->id]) || empty($OriginData[$Field->id])) {
            return false;
        }
        //====================================================================//
        // Check if Fields Should be Tested or Not
        if (!$Field->notest) {
            return false;
        }
        return true;
    }
    
    /**
     *   @abstract   Create Fake/Dummy Object List Data
     *
     *   @param      array   $Field          Object Field Definition
     *
     *   @return     int     $result     0 if KO, 1 if OK
     */
    public function fakeListData($Field)
    {
        //====================================================================//
        // Read Number of Items to Put in Lists
        $NbItems =  $this->settings["ListItems"]?$this->settings["ListItems"]:2;
        //====================================================================//
        // Parse List Identifiers
        $List   =   self::isListField($Field->id);
        $Type   =   self::isListField($Field->type);
        
        //====================================================================//
        // Generate Unik Dummy Fields Data
        $ListData = array();
        while (count($ListData) < $NbItems) {
            $Data           =   self::fakeFieldData($Type["fieldname"], $Field->choices, $Field->options);
            $Md5            =   md5(serialize($Data));
            $ListData[$Md5] =   $Data;
        }

        //====================================================================//
        // Create Dummy List Data
        $Out = array();
{'fraction_non_alphanumeric': 0.3393776035285469, 'fraction_numerical': 0.00098015192354815, 'mean_word_length': 1.9188271053102093, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 63, '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': '3211290', 'n_tokens_mistral': 3732, 'n_tokens_neox': 3452, 'n_words': 838}