Skip to content

Commit

Permalink
Рефакторинг поведения для переводов. Теперь переводы загружаются сраз…
Browse files Browse the repository at this point in the history
…у все через relation. Лишних запросов не делается.
  • Loading branch information
maddoger committed Feb 22, 2015
1 parent 0fe2ee6 commit bc4930e
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 36 deletions.
53 changes: 19 additions & 34 deletions i18n/TranslatableBehavior.php
Expand Up @@ -10,6 +10,7 @@
use yii\base\Behavior;
use yii\base\InvalidParamException;
use yii\db\ActiveRecord;
use yii\log\Logger;

/**
* TranslatableBehavior
Expand Down Expand Up @@ -132,7 +133,7 @@ public function canGetProperty($name, $checkVars = true)
*/
public function afterFind($event)
{
$this->populateTranslations();
$this->loadTranslations();
$this->getTranslation($this->getLanguage());
}

Expand Down Expand Up @@ -170,8 +171,6 @@ public function setTranslationAttribute($attribute, $value)
$this->{$attribute} = $value;
}



/**
* Sets current model's language
*
Expand All @@ -181,7 +180,7 @@ public function setLanguage($value)
{
//$value = strtolower($value);
if (!isset($this->_models[$value])) {
$this->_models[$value] = $this->loadTranslation($value);
$this->_models[$value] = $this->getNewTranslation($value);
}
$this->_language = $value;
}
Expand Down Expand Up @@ -293,7 +292,7 @@ public function getTranslation($language = null)
$language = $this->getLanguage();
}
if (!isset($this->_models[$language])) {
$this->_models[$language] = $this->loadTranslation($language);
$this->_models[$language] = $this->getNewTranslation($language);
}
return $this->_models[$language];
}
Expand All @@ -307,16 +306,6 @@ public function getAvailableLanguages()
{
if (!empty($this->_models)) {
return array_keys($this->_models);
} else {
/** @var \yii\db\ActiveQuery $relation */
$relation = $this->owner->getRelation($this->relation);
/** @var ActiveRecord $class */
$class = $relation->modelClass;
if ($this->owner->getPrimarykey()) {
return $class::find()->select([$this->languageAttribute])->where(
[key($relation->link) => $this->owner->getPrimarykey()]
)->orderBy([$this->languageAttribute => SORT_ASC])->column($this->owner->getDb());
}
}
return null;
}
Expand Down Expand Up @@ -399,43 +388,39 @@ private function isTranslationActive($model)
*
* @return null|\yii\db\ActiveQuery|static
*/
private function loadTranslation($language)
private function getNewTranslation($language)
{
$translation = null;
/** @var \yii\db\ActiveQuery $relation */
$relation = $this->owner->getRelation($this->relation);
/** @var ActiveRecord $class */
$class = $relation->modelClass;
if ($this->owner->getPrimarykey()) {
$translation = $class::findOne(
[$this->languageAttribute => $language, key($relation->link) => $this->owner->getPrimarykey()]
);
}
if ($translation === null) {
$translation = new $class;
$translation->{key($relation->link)} = $this->owner->getPrimaryKey();
$translation->{$this->languageAttribute} = $language;
}
//if ($translation === null) {
$translation = new $class;
$translation->{key($relation->link)} = $this->owner->getPrimaryKey();
$translation->{$this->languageAttribute} = $language;
//}
return $translation;
}

/**
* Populates already loaded translations
* Loads relation to models
* @return bool
*/
private function populateTranslations()
private function loadTranslations()
{
//translations
$aRelated = $this->owner->getRelatedRecords();
if (isset($aRelated[$this->relation]) && $aRelated[$this->relation] != null) {
if (is_array($aRelated[$this->relation])) {
foreach ($aRelated[$this->relation] as $model) {
if ($related = $this->owner->{$this->relation}) {
if (is_array($related)) {
foreach ($related as $model) {
$this->_models[$model->getAttribute($this->languageAttribute)] = $model;
}
} else {
$model = $aRelated[$this->relation];
$model = $related;
$this->_models[$model->getAttribute($this->languageAttribute)] = $model;
}
return true;
}
return false;
}

/**
Expand Down
98 changes: 96 additions & 2 deletions i18n/TranslatableModelBehavior.php
Expand Up @@ -59,6 +59,11 @@ class TranslatableModelBehavior extends Behavior
*/
private $_language;

/**
* @var array translation is active if at least one of this attributes is set.
*/
public $requiredAttributes;

/**
* Make [[$translationAttributes]] writable
* @param string $name
Expand Down Expand Up @@ -123,6 +128,8 @@ public function setLanguage($value)
$this->_language = $value;
}



/**
* Returns current models' language. If null, will return app's configured language.
* @return string
Expand All @@ -133,7 +140,16 @@ public function getLanguage()
if ($this->defaultLanguageAttribute) {
$this->_language = $this->owner->{$this->defaultLanguageAttribute};
}
//var_dump($this->owner->{$this->defaultLanguageAttribute}, $this->_language);
//Try find best language from available
$availableLanguages = $this->getAvailableLanguages();
if ($availableLanguages) {
if (in_array(Yii::$app->language, $availableLanguages)) {
$this->_language = Yii::$app->language;
} elseif (Yii::$app->has('request')) {
$this->_language = Yii::$app->request->getPreferredLanguage($availableLanguages);
}
}
//Use application language, because we don`t have any translation yet
if (!$this->_language) {
$this->_language = Yii::$app->language;
}
Expand Down Expand Up @@ -169,7 +185,7 @@ public function setTranslationAttribute($attribute, $value)
public function hasTranslation($language = null)
{
$translation = $this->getTranslation($language);
return $translation && $translation->validate();
return $translation && $this->isTranslationActive($translation);
}

/**
Expand All @@ -192,6 +208,61 @@ public function getTranslation($language = null)
return $this->owner->{$this->translationsAttribute}[$language];
}

/**
* Returns array of available languages.
* Populated models will be used if its set, otherwise query will be used.
* @return array
*/
public function getAvailableLanguages()
{
if (!empty($this->owner->{$this->translationsAttribute})) {
return array_keys($this->owner->{$this->translationsAttribute});
}
return null;
}


/**
* Load owner model and translation models from data.
* @param $data
* @param null $languages array of languages for loading
* @param null $formName
* @param null $translationFormName
* @return bool
*/
public function loadWithTranslations($data, $languages, $formName = null, $translationFormName = null)
{
if ($this->owner->load($data, $formName)) {
if (!$languages) {
throw new InvalidParamException('Languages must be set.');
}
foreach ($languages as $language) {
$modelI18n = static::getTranslation($language);
$modelI18n->load($data, $translationFormName);
}
return true;
}
return false;
}

/**
* At least one translation must be valid.
* Each translation must be active (with one of required attributes) and validates itself.
* @return bool
*/
public function validateTranslations()
{
$valid = !empty($this->owner->{$this->translationsAttribute});
$activeTranslations = 0;
foreach ($this->owner->{$this->translationsAttribute} as $model) {
if ($this->isTranslationActive($model)) {
$activeTranslations++;
$valid = $valid && $model->validate();
}
}
return $activeTranslations>0 && $valid;
}

/**
* Loads all specified languages. For example:
*
Expand All @@ -213,6 +284,29 @@ public function loadTranslations($languages)
}
}


/**
* Translation is active or just empty model?
* @param $model
* @return bool
*/
private function isTranslationActive($model)
{
if (!$model) {
return false;
}
if (is_array($this->requiredAttributes) && !empty($this->requiredAttributes)) {
foreach ($this->requiredAttributes as $attribute) {
if ($model->{$attribute} && !empty($model->{$attribute})) {
return true;
}
}
} else {
return true;
}
return false;
}

/**
* Loads a specific translation model
*
Expand Down

0 comments on commit bc4930e

Please sign in to comment.