language = $language; $this->theme = $theme; } public function getLastModifiedTime(): ?int { $translationFiles = $this->getTranslationFiles(); if (null === $translationFiles) { return null; } $lastModifiedTime = []; foreach ($translationFiles as $file) { $lastModifiedTime[] = filemtime($file); } return max($lastModifiedTime); } public function translate(string $language): bool { $translationFiles = $this->getTranslationFiles(); if (null === $translationFiles) { return false; } $this->translateModels($language, $translationFiles); return true; } protected function getTranslationFiles(): ?array { $translationFiles = $this->findTranslationFiles($this->language); if (null === $translationFiles) { return null; } if (null !== $this->theme) { $themeTranslationFiles = $this->findTranslationFiles($this->language, $this->theme->getTheme()); if (null !== $themeTranslationFiles) { $translationFiles = array_merge($translationFiles, $themeTranslationFiles); } } return $translationFiles; } protected function findTranslationFiles(string $language, ?string $theme = null): ?array { $path = sfConfig::get('sf_data_dir') . '/translation/' . $language; $path .= null !== $theme ? '/' . $theme : '/all'; if (!is_dir($path)) { return null; } return glob($path . '/*yml'); } protected function translateModels(string $language, array $translationFiles) { $logging = sfConfig::get('sf_logging_enabled'); // wyłączamy logowanie, aby nie przekroczyć dozwolonej pamięci przy tylu operacjach odczytu i zapisu sfConfig::set('sf_logging_enabled', false); foreach ($translationFiles as $file) { $modelClass = basename($file, '.yml'); $modelClassPeer = $modelClass . 'Peer'; $fieldTranslations = sfYaml::load($file); if (!class_exists($modelClass)) { throw new sfException(sprintf('Model class "%s" does not exist', $modelClass)); } $offset = 0; $count = $this->getFieldTranslationCount($fieldTranslations, $modelClassPeer); $c = $this->getModelCriteria($modelClass); do { $c->setOffset($offset); $c->setLimit(20); $models = call_user_func([$modelClassPeer, 'doSelectWithI18n'], $c, self::BASE_LANGUAGE); foreach ($models as $model) { $update = false; foreach ($fieldTranslations as $fieldName => $translations) { $phpName = sfInflector::camelize($fieldName); $getter = 'get' . $phpName; $setter = 'set' . $phpName; $optGetter = 'getOpt' . $phpName; $model->setCulture(self::BASE_LANGUAGE); $value = $model->$getter(); $model->setCulture($language); if (isset($translations[$value]) && (!method_exists($model, $optGetter) || $model->$getter() == $model->$optGetter())) { $model->$setter($translations[$value]); $update = true; } } if ($update) { $model->save(); } } $offset += count($models); } while($offset > 0 && $offset < $count); } sfConfig::set('sf_logging_enabled', $logging); } protected function getFieldTranslationCount(array $fieldTranslations, string $modelClassPeer): int { $count = []; foreach ($fieldTranslations as $translations) { $count[] = count($translations); } $c = new Criteria(); $this->addThemeCriteria($modelClassPeer, $c); $entityCount = call_user_func([$modelClassPeer, 'doCount'], $c); return min(max($count), $entityCount); } protected function getModelCriteria(string $modelClass): Criteria { $c = new Criteria(); $entity = new $modelClass(); foreach ($entity->getPrimaryKeyFields(BasePeer::TYPE_COLNAME) as $column) { $c->addAscendingOrderByColumn($column); } $this->addThemeCriteria($modelClass . 'Peer', $c); return $c; } protected function addThemeCriteria(string $modelClassPeer, Criteria $c) { $themeIdField = "{$modelClassPeer}::THEME_ID"; if (defined($themeIdField)) { $c->add(constant($themeIdField), $this->theme->getId()); } } }