PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/Translate/Model/Behavior/CroogoTranslateBehavior.php

https://github.com/kareypowell/croogo
PHP | 302 lines | 160 code | 37 blank | 105 comment | 33 complexity | 45ede85fc72d5103fd49ddc8d056fd58 MD5 | raw file
  1. <?php
  2. App::uses('ModelBehavior', 'Model');
  3. App::uses('AppModel', 'Model');
  4. /**
  5. * CroogoTranslate Behavior
  6. *
  7. * Modified version of cake's core TranslateBehavior.
  8. * If no translated record is found for the locale, the main record will be returned.
  9. * TranslateBehavior used to return nothing in that case.
  10. *
  11. * @category Behavior
  12. * @package Croogo.Translate.Model.Behavior
  13. * @version 1.0
  14. * @author Fahad Ibnay Heylaal <contact@fahad19.com>
  15. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  16. * @link http://www.croogo.org
  17. */
  18. class CroogoTranslateBehavior extends ModelBehavior {
  19. /**
  20. * Used for runtime configuration of model
  21. */
  22. public $runtime = array();
  23. /**
  24. * Field names
  25. *
  26. * @var array
  27. */
  28. public $translationFields = array();
  29. /**
  30. * Callback
  31. *
  32. * $config for CroogoTranslateBehavior should be
  33. * array( 'fields' => array('field_one',
  34. * 'field_two' => 'FieldAssoc', 'field_three'))
  35. *
  36. * With above example only one permanent hasMany will be joined (for field_two
  37. * as FieldAssoc)
  38. *
  39. * $config could be empty - and translations configured dynamically by
  40. * bindTranslation() method
  41. *
  42. * @param Model $model
  43. * @param array $config
  44. * @return mixed
  45. * @access public
  46. */
  47. public function setup(Model $model, $config = array()) {
  48. $db = ConnectionManager::getDataSource($model->useDbConfig);
  49. if (!$db->connected) {
  50. trigger_error(
  51. __d('croogo', 'Datasource %s for CroogoTranslateBehavior of model %s is not connected', $model->useDbConfig, $model->alias),
  52. E_USER_ERROR
  53. );
  54. return false;
  55. }
  56. $this->settings[$model->alias] = array();
  57. $this->runtime[$model->alias] = array('fields' => array());
  58. $this->translateModel($model);
  59. $this->translationFields[$model->alias] = $config['fields'];
  60. //return $this->bindTranslation($model, $config, false);
  61. }
  62. /**
  63. * Callback
  64. *
  65. * @return void
  66. * @access public
  67. */
  68. public function cleanup(Model $model) {
  69. //$this->unbindTranslation($model);
  70. unset($this->settings[$model->alias]);
  71. unset($this->runtime[$model->alias]);
  72. }
  73. /**
  74. * Get field names for Translation
  75. *
  76. * @param object $model
  77. * @return array
  78. * @access public
  79. */
  80. public function getTranslationFields(Model $model) {
  81. if (Hash::numeric(array_keys($this->translationFields[$model->alias]))) {
  82. return $this->translationFields[$model->alias];
  83. } else {
  84. return array_keys($this->translationFields[$model->alias]);
  85. }
  86. }
  87. /**
  88. * afterFind Callback
  89. *
  90. * @param array $results
  91. * @param boolean $primary
  92. * @return array Modified results
  93. * @access public
  94. */
  95. public function afterFind(Model $model, $results, $primary = false) {
  96. $locale = $this->_getLocale($model);
  97. if (empty($locale) || empty($results)) {
  98. return $results;
  99. }
  100. $fields = $this->getTranslationFields($model);
  101. $RuntimeModel = $this->translateModel($model);
  102. if ($primary && isset($results[0][$model->alias])) {
  103. $i = 0;
  104. foreach ($results as $result) {
  105. if (!isset($result[$model->alias][$model->primaryKey])) {
  106. continue;
  107. }
  108. $translations = $RuntimeModel->find('all', array(
  109. 'conditions' => array(
  110. $RuntimeModel->alias . '.model' => $model->alias,
  111. $RuntimeModel->alias . '.foreign_key' => $result[$model->alias][$model->primaryKey],
  112. $RuntimeModel->alias . '.field' => $fields,
  113. ),
  114. ));
  115. foreach ($translations as $translation) {
  116. $field = $translation[$RuntimeModel->alias]['field'];
  117. // Original row
  118. /*if (isset($results[$i][$model->alias][$field])) {
  119. $results[$i][$field.'Original'] = $results[$i][$model->alias][$field];
  120. }*/
  121. // Translated row
  122. if ($translation[$RuntimeModel->alias]['locale'] == $locale &&
  123. isset($results[$i][$model->alias][$field])) {
  124. $results[$i][$model->alias][$field] = $translation[$RuntimeModel->alias]['content'];
  125. }
  126. // Other translations
  127. if (!Hash::numeric(array_keys($this->translationFields[$model->alias])) &&
  128. isset($results[$i][$model->alias][$field])) {
  129. if (!isset($results[$i][$field . 'Translation'])) {
  130. $results[$i][$field . 'Translation'] = array();
  131. }
  132. $results[$i][$field . 'Translation'][] = $translation[$RuntimeModel->alias];
  133. }
  134. }
  135. $i++;
  136. }
  137. }
  138. return $results;
  139. }
  140. /**
  141. * Save translation only (in i18n table)
  142. *
  143. * @param object $model
  144. * @param array $data
  145. * @param boolean $validate
  146. */
  147. public function saveTranslation(Model $model, $data = null, $validate = true) {
  148. $model->data = $data;
  149. if (!isset($model->data[$model->alias])) {
  150. return false;
  151. }
  152. $locale = $this->_getLocale($model);
  153. if (empty($locale)) {
  154. return false;
  155. }
  156. $RuntimeModel = $this->translateModel($model);
  157. $RuntimeModel->Behaviors->attach('Croogo.Trackable');
  158. $conditions = array('model' => $model->alias, 'foreign_key' => $model->id);
  159. foreach ($model->data[$model->alias] as $field => $value) {
  160. unset($conditions['content']);
  161. $conditions['field'] = $field;
  162. if (is_array($value)) {
  163. $conditions['locale'] = array_keys($value);
  164. } else {
  165. $conditions['locale'] = $locale;
  166. if (is_array($locale)) {
  167. $value = array($locale[0] => $value);
  168. } else {
  169. $value = array($locale => $value);
  170. }
  171. }
  172. $translations = $RuntimeModel->find('list', array('conditions' => $conditions, 'fields' => array($RuntimeModel->alias . '.locale', $RuntimeModel->alias . '.id')));
  173. foreach ($value as $_locale => $_value) {
  174. $RuntimeModel->create();
  175. $conditions['locale'] = $_locale;
  176. $conditions['content'] = $_value;
  177. if (array_key_exists($_locale, $translations)) {
  178. $created = false;
  179. if (!$RuntimeModel->save(array($RuntimeModel->alias => array_merge($conditions, array('id' => $translations[$_locale]))))) {
  180. return false;
  181. }
  182. } else {
  183. $created = true;
  184. if (!$RuntimeModel->save(array($RuntimeModel->alias => $conditions))) {
  185. return false;
  186. }
  187. }
  188. }
  189. if ($model->Behaviors->loaded('Cached')) {
  190. $model->Behaviors->trigger(
  191. 'afterSave',
  192. array($model, $created),
  193. array('breakOn' => array('Cached'))
  194. );
  195. }
  196. }
  197. return true;
  198. }
  199. /**
  200. * afterDelete Callback
  201. *
  202. * @return void
  203. * @access public
  204. */
  205. public function afterDelete(Model $model) {
  206. $RuntimeModel = $this->translateModel($model);
  207. $conditions = array('model' => $model->alias, 'foreign_key' => $model->id);
  208. $RuntimeModel->deleteAll($conditions);
  209. }
  210. /**
  211. * Get selected locale for model
  212. *
  213. * @return mixed string or false
  214. * @access protected
  215. */
  216. protected function _getLocale(Model $model) {
  217. if (!isset($model->locale) || is_null($model->locale)) {
  218. /*
  219. if (!class_exists('I18n')) {
  220. App::import('Core', 'i18n');
  221. }
  222. $I18n = I18n::getInstance();
  223. $I18n->l10n->get(Configure::read('Config.language'));
  224. $model->locale = $I18n->l10n->locale;
  225. */
  226. $model->locale = Configure::read('Config.language');
  227. }
  228. return $model->locale;
  229. }
  230. /**
  231. * Get instance of model for translations
  232. *
  233. * @return object
  234. * @access public
  235. */
  236. public function &translateModel(Model $model) {
  237. if (!isset($this->runtime[$model->alias]['model'])) {
  238. if (!isset($model->translateModel) || empty($model->translateModel)) {
  239. $className = 'I18nModel';
  240. } else {
  241. $className = $model->translateModel;
  242. }
  243. $this->runtime[$model->alias]['model'] = ClassRegistry::init($className, 'Model');
  244. }
  245. if (!empty($model->translateTable) && $model->translateTable !== $this->runtime[$model->alias]['model']->useTable) {
  246. $this->runtime[$model->alias]['model']->setSource($model->translateTable);
  247. } elseif (empty($model->translateTable) && empty($model->translateModel)) {
  248. $this->runtime[$model->alias]['model']->setSource('i18n');
  249. }
  250. return $this->runtime[$model->alias]['model'];
  251. }
  252. }
  253. if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) {
  254. /**
  255. * @package Croogo.Translate.Model.Behavior
  256. */
  257. class I18nModel extends AppModel {
  258. public $name = 'I18nModel';
  259. public $useTable = 'i18n';
  260. public $displayField = 'field';
  261. public $actsAs = array(
  262. 'Croogo.Cached' => array(),
  263. );
  264. }
  265. }