<commit_before><?php namespace Mosaiqo\Translatable;

use Illuminate\Database\Eloquent\Collection;
use Mosaiqo\Translatable\Exceptions\AttributeNotTranslatable;
use Mosaiqo\Translatable\Exceptions\LocaleNotDefinedException;

/**
 * Class Translatable
 *
 * @package Mosaiqo\Translatable
 */
trait Translatable
{
	/**
	 * @var array
	 */
	protected $currentLocales = [];

	/**
	 * @var array
	 */
	static protected $availableLocales = [];


	/**
	 * Boots up the trait and doo some necessary stuff
	 * before it can be used.
	 */
	public static function bootTranslatable()
	{
		// Set available locales for the app
		self::$availableLocales = (array) config('translatable.locales', [] );
	}

	/**
	 * Declares the relation for the locales.
	 * @return mixed
	 */
	public function locales()
	{
		return $this->embedsOne( \Mosaiqo\Translatable\Models\Locale::class, 'locales' );
	}

	/**
	 * Return or create a new locale for the given localeCode
	 * @param string $localeCode Locale ISO code for the language
	 *
	 * @return mixed|null
	 */
	protected function locale( $localeCode, $parameters = [] )
	{
		$localeTranslation = null;

		if ( $locales = $this->locales()->getResults() )
		{
			$localeTranslation = $locales->$localeCode()->getResults();

			if(! $this->hasTranslation( $localeCode ))
			{
				$localeTranslation = $this->createNewLocaleTranslation( $parameters );
			}
		}

		if (!$localeTranslation )
		{
			$localeTranslation = $this->createNewLocaleTranslation($parameters);

			if($this->exists)
			{
				$locale = $this->locales()->getResults();
				$locale->$localeCode()->save( $localeTranslation );
				$this->locales()->save( $locale );
				$this->save();
			}
		}

		return $this->currentLocales[$localeCode] = $localeTranslation;
	}

	/**
	 * Fill the model with an array of attributes.
	 *
	 * @param  array $attributes
	 *
	 * @return $this
	 *
	 */
	public function fill( array $attributes )
	{

		$attributesForParent = $this->fillLocales( $attributes );

		return parent::fill( $attributesForParent );
	}

	/**
	 * @param $attribute
	 *
	 * @return mixed
	 */
	public function __get( $attribute )
	{
		if ( in_array( $attribute, $this->getTranslatableAttributes() ) )
		{
			$locale = app()->getLocale();
			return $this->locale( $locale )->$attribute;
		}

		return parent::__get( $attribute );
	}

	/**
	 * @param string $method
	 * @param array  $parameters
	 *
	 * @return mixed|void
	 */
	public function __call( $method, $parameters )
	{
		if ( in_array( $method, $this->getAvailableLocales() ) )
		{
			return $this->locale( $method, $parameters);
		}

		return parent::__call( $method, $parameters );
	}


	/**
	 * Save the model to the database.
	 *
	 * @param  array $options
	 *
	 * @throws AttributeNotTranslatable
	 * @return bool
	 */
	public function save( array $options = [ ] )
	{
		if ( $this->getAttribute('locales') )
			$localeTranslation = $this->locales()->getResults();
		else
			$localeTranslation = $this->locales()->create([]);


		foreach ( $this->currentLocales as $locale => $currentLocale )
		{
			if($this->isTranslatable( $currentLocale ))
			{

				if($this->isCustomIdEnabled())
				{
					$keyname = $this->getKeyName();
					$currentLocale->$keyname = $locale;
				}

				$currentLocale->fireModelEvent('saving');
				$localeTranslation->$locale()->save( $currentLocale );
			}
		}

		$localeTranslation->fireModelEvent( 'saving' );
		$this->locales()->associate( $localeTranslation );

		$this->currentLocales = [];

		return parent::save( $options );
	}


	/**
	 * Translates a to a given localeCode
	 *
	 * @param      $locale
	 *
	 * @param bool $withFallback
	 *
	 * @return Model
	 * @throws LocaleNotDefinedException
	 */
	public function translate($locale , $withFallback = null)
	{

		if ( ! $this->hasTranslation( $locale ) )
		{
			if(is_string($withFallback))
			{<commit_msg>Fix bug with recurrent async calls to an API<commit_after><?php namespace Mosaiqo\Translatable;

use Illuminate\Database\Eloquent\Collection;
use Mosaiqo\Translatable\Exceptions\AttributeNotTranslatable;
use Mosaiqo\Translatable\Exceptions\LocaleNotDefinedException;

/**
 * Class Translatable
 *
 * @package Mosaiqo\Translatable
 */
trait Translatable
{
	/**
	 * @var array
	 */
	protected $currentLocales = [];

	/**
	 * @var array
	 */
	static protected $availableLocales = [];


	/**
	 * Boots up the trait and doo some necessary stuff
	 * before it can be used.
	 */
	public static function bootTranslatable()
	{
		// Set available locales for the app
		self::$availableLocales = (array) config('translatable.locales', [] );
	}

	/**
	 * Declares the relation for the locales.
	 * @return mixed
	 */
	public function locales()
	{
		return $this->embedsOne( \Mosaiqo\Translatable\Models\Locale::class, 'locales' );
	}

	/**
	 * Return or create a new locale for the given localeCode
	 * @param string $localeCode Locale ISO code for the language
	 *
	 * @return mixed|null
	 */
	protected function locale( $localeCode, $parameters = [] )
	{
		$localeTranslation = null;

		if ( $locales = $this->locales()->getResults() )
		{
			$localeTranslation = $locales->$localeCode()->getResults();

			if(! $this->hasTranslation( $localeCode ))
			{
				$localeTranslation = $this->createNewLocaleTranslation( $parameters );
			}
		}

		if (!$localeTranslation )
		{
			$localeTranslation = $this->createNewLocaleTranslation($parameters);

			if($this->exists)
			{
				$locale = $this->locales()->getResults();
				$locale->$localeCode()->save( $localeTranslation );
				$this->locales()->save( $locale );
				$this->save();
			}
		}

		return $this->currentLocales[$localeCode] = $localeTranslation;
	}

	/**
	 * Fill the model with an array of attributes.
	 *
	 * @param  array $attributes
	 *
	 * @return $this
	 *
	 */
	public function fill( array $attributes )
	{

		$attributesForParent = $this->fillLocales( $attributes );

		return parent::fill( $attributesForParent );
	}

	/**
	 * @param $attribute
	 *
	 * @return mixed
	 */
	public function __get( $attribute )
	{
		if ( in_array( $attribute, $this->getTranslatableAttributes() ) )
		{
			$locale = app()->getLocale();
			return $this->locale( $locale )->$attribute;
		}

		return parent::__get( $attribute );
	}

	/**
	 * @param string $method
	 * @param array  $parameters
	 *
	 * @return mixed|void
	 */
	public function __call( $method, $parameters )
	{
		if ( in_array( $method, $this->getAvailableLocales() ) )
		{
			return $this->locale( $method, $parameters);
		}

		return parent::__call( $method, $parameters );
	}


	/**
	 * Save the model to the database.
	 *
	 * @param  array $options
	 *
	 * @throws AttributeNotTranslatable
	 * @return bool
	 */
	public function save( array $options = [ ] )
	{
		if ( $this->getAttribute('locales') )
			$localeTranslation = $this->locales()->getResults();
		else
			$localeTranslation = $this->locales()->create([]);


		foreach ( $this->currentLocales as $locale => $currentLocale )
		{
			if($this->isTranslatable( $currentLocale ))
			{

				if($this->isCustomIdEnabled())
				{
					$keyname = $this->getKeyName();
					$currentLocale->$keyname = $locale;
				}

				$currentLocale->fireModelEvent('saving');
				// This is placed here in favor to make async calls from the frontend.
				if($localeTranslation->$locale)
				{
					$localeTranslation->$locale()->performUpdate($currentLocale);
				}
				else
				{				
					$localeTranslation->$locale()->save( $currentLocale );
				}
			}
		}

		$localeTranslation->fireModelEvent( 'saving' );
		$this->locales()->associate( $localeTranslation );

		$this->currentLocales = [];

		return parent::save( $options );
	}


	/**
	 * Translates a to a given localeCode
	 *
	 * @param      $locale
	 *
	 * @param bool $withFallback
	 *
	 * @return Model
	 * @throws LocaleNotDefinedException
	 */
	public function translate($locale , $withFallback = null)
	{

		if ( ! $this->hasTranslation( $locale ) )
		{
			if(is_string($withFallback))
			{
{'fraction_non_alphanumeric': 0.15323695788812067, 'fraction_numerical': 0.0, 'mean_word_length': 3.4746906636670416, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 92, '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': '4803175', 'n_tokens_mistral': 2860, 'n_tokens_neox': 2481, 'n_words': 548}