· 7 years ago · Mar 03, 2019, 12:58 PM
1<?php namespace Libraries\Core;
2
3/**
4 * How to use :
5 *
6 * setup your configuration :
7 *
8 * in Config/App search for $defaultLocale and configure your $supportedLocales
9 *
10 *
11 * setup your model :
12 *
13 * <?php namespace App\Models;
14 *
15 * use Libraries\Core\MY_I18n_Model;
16 *
17 * class JobModel extends MY_I18n_Model
18 * {
19 * protected $table = 'jobs';
20 * protected $primaryKey = 'id';
21 *
22 * protected $i18nTable = 'jobs_i18n';
23 * // protected $autofillEmptyFields = true;
24 * protected $i18nKeys = [
25 * 'title'
26 * ];
27 *
28 * [...]
29 * }
30 *
31 * Setup your database
32 *
33 * CREATE TABLE IF NOT EXISTS `jobs` (
34 * `id` int(11) NOT NULL AUTO_INCREMENT,
35 * `title` varchar(50) NOT NULL,
36 * `created_at` datetime NOT NULL,
37 * `updated_at` datetime DEFAULT NULL,
38 * `deleted` tinyint(1) NOT NULL DEFAULT '0',
39 * `deleted_at` datetime DEFAULT NULL,
40 * PRIMARY KEY (`id`)
41 * ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
42 *
43 * CREATE TABLE IF NOT EXISTS `jobs_i18n` (
44 * `id` int(11) NOT NULL AUTO_INCREMENT,
45 * `jobs_id` int(11) NOT NULL,
46 * `locale` varchar(7) NOT NULL,
47 * `key` varchar(127) NOT NULL,
48 * `value` varchar(127) NOT NULL,
49 * PRIMARY KEY (`id`),
50 * UNIQUE KEY `unique fileds` (`locale`,`key`,`jobs_id`)
51 * ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
52 *
53 *
54 *
55 * the idea is that your key title will automaticaly replaced by the good locale.
56 *
57 * afterFind : your key title will be replaced by the key title in the _i18n table
58 * afterUpdate, your key title will be updated and your _i18n reference too
59 * afterInsert, your key will be created in all $supportedLocales.
60 * if $autofillEmptyFields set to true,all key will take the new value.
61 * if set to false, only $currentLocale will be inserted, the other stay empty
62 * afterDelete. if $useSoftDelete set to true, nothing happens, if set to false, all jobs_id will be removed
63 *
64 * You can use multiple keys per jobs_id. title, description, short_description, [...] as many as you want.
65 *
66 * thats it !! :)
67 */
68
69use CodeIgniter\Database\BaseBuilder;
70
71use Config\App;
72use CodeIgniter\Model;
73
74class MY_I18n_Model extends Model
75{
76
77 /**
78 * locale detection Accept-Language Header - fallback on \Config\App::$defaultLanguage
79 *
80 * @var string
81 */
82 private $currentLocale;
83
84 /**
85 * represent the i18n table_name
86 *
87 * @var string
88 */
89 protected $i18nTable;
90
91 /**
92 * new instance of the query builder
93 *
94 * @var BaseBuilder
95 */
96 protected $i18nBuilder;
97
98 /**
99 * list of keys to translate
100 *
101 * @var array
102 */
103 protected $i18nKeys = [];
104
105 /**
106 * Autofill empty value on insert ?
107 *
108 * @var boolean
109 */
110 protected $autofillEmptyFields = false;
111
112 public function __construct()
113 {
114 parent::__construct();
115
116 $this->searchI18nTable();
117 }
118
119 /**
120 * Looking for an existing table
121 */
122 protected function searchI18nTable()
123 {
124 if ($this->db->tableExists($this->i18nTable)) {
125 $this->currentLocale = service('request')->getLocale();
126 $this->i18nBuilder = new BaseBuilder($this->i18nTable, $this->db);
127
128 $this->afterFind[] = 'i18nAfterFind';
129 $this->afterInsert[] = 'i18nAfterInsert';
130 $this->afterUpdate[] = 'i18nAfterUpdate';
131 $this->afterDelete[] = 'i18nAfterDelete';
132 }
133 }
134
135 /**
136 * after Selecting data if single record or multiples.
137 *
138 * @param array $vars The resulting row of data
139 *
140 * @return array The resulting row of data.
141 */
142 protected function i18nAfterFind($vars)
143 {
144 $data_tmp = null;
145
146 if (!is_null($vars['data'])) {
147 if (isset($vars['id'])) {
148 $data_tmp = $this->joinI18n($vars['data']);
149 }
150 else
151 {
152 $data_tmp = [];
153 foreach ($vars['data'] as $data)
154 {
155 $data_tmp[] = $this->joinI18n($data);
156 }
157 }
158 }
159
160 $vars['data'] = $data_tmp;
161
162 return $vars;
163 }
164
165 /**
166 * after Selecting, data is parsed.
167 *
168 * @param array $data The resulting row of data
169 *
170 * @return array The resulting row of data.
171 */
172 protected function joinI18n($data)
173 {
174 $i18n_query = $this->i18nBuilder
175 ->where('locale', $this->currentLocale)
176 ->where($this->table . '_id', $data['id'])
177 ->get();
178
179 foreach ($i18n_query->getResult() as $row)
180 {
181 $data[$row->key] = $row->value;
182 }
183
184 return $data;
185 }
186
187 /**
188 * after Delete
189 *
190 * @param array $vars The resulting row of data
191 *
192 * @return array The resulting row of data.
193 */
194 protected function i18nAfterDelete($vars)
195 {
196 if ($vars['purge'] === true) {
197 $this->i18nBuilder
198 ->where($this->table . '_id', $vars['id'])
199 ->delete();
200 }
201
202 return $vars;
203 }
204
205 /**
206 * after Update
207 *
208 * @param array $vars The resulting row of data
209 *
210 * @return array The resulting row of data.
211 */
212 protected function i18nAfterUpdate($vars)
213 {
214 // foreach keys
215 foreach($vars['data'] as $k => $v)
216 {
217 // If my currentKey is in my $i18nKeys
218 if (in_array($k, $this->i18nKeys)) {
219 $this->i18nBuilder
220 ->where('locale', $this->currentLocale)
221 ->where($this->table . '_id', $vars['id'])
222 ->where('key', $k)
223 ->update(['value' => $v]);
224 }
225 }
226
227 return $vars;
228 }
229
230 /**
231 * after Insert
232 *
233 * @param array $vars The resulting row of data
234 *
235 * @return array The resulting row of data.
236 */
237 protected function i18nAfterInsert($vars)
238 {
239 $app_config = new \Config\App();
240
241 $relatedId = $this->db->insertID();
242
243 // For all keys
244 foreach($vars['data'] as $k => $v)
245 {
246 // If my currentKey is in my $i18nKeys
247 if (in_array($k, $this->i18nKeys))
248 {
249 // And for each locales
250 foreach($app_config->supportedLocales as $locale)
251 {
252 // if autoFill == true
253 // Set very i18n keys with the same data
254 if ($this->autofillEmptyFields)
255 {
256 $data = [
257 $this->table . '_id' => $relatedId,
258 'locale' => $locale,
259 'key' => $k,
260 'value' => $v,
261 ];
262 }
263 // if autofill = false
264 // fill current key and let the others empty
265 else
266 {
267 $data = [
268 $this->table . '_id' => $relatedId,
269 'locale' => $locale,
270 'key' => $k,
271 ];
272 // select good locale
273 if ($locale == $this->currentLocale)
274 {
275 $data['value'] = $v;
276 }
277 // other fields are empty
278 else
279 {
280 $data['value'] = '';
281 }
282 }
283
284 // insert
285 $this->i18nBuilder->insert($data);
286 }
287 }
288 }
289
290 return $vars;
291 }
292
293}