PageRenderTime 64ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/app/models/behaviors/croogo_translate.php

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