CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.6 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.6
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Acl
        • Auth
    • Core
    • Error
    • Event
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
      • Validator
    • Network
      • Email
      • Http
    • Routing
      • Filter
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

  • AclBehavior
  • ContainableBehavior
  • TranslateBehavior
  • TreeBehavior
  1: <?php
  2: /**
  3:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4:  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5:  *
  6:  * Licensed under The MIT License
  7:  * For full copyright and license information, please see the LICENSE.txt
  8:  * Redistributions of files must retain the above copyright notice.
  9:  *
 10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 11:  * @link          http://cakephp.org CakePHP(tm) Project
 12:  * @package       Cake.Model.Behavior
 13:  * @since         CakePHP(tm) v 1.2.0.4525
 14:  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 15:  */
 16: 
 17: App::uses('ModelBehavior', 'Model');
 18: App::uses('I18n', 'I18n');
 19: App::uses('I18nModel', 'Model');
 20: 
 21: /**
 22:  * Translate behavior
 23:  *
 24:  * @package       Cake.Model.Behavior
 25:  * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/translate.html
 26:  */
 27: class TranslateBehavior extends ModelBehavior {
 28: 
 29: /**
 30:  * Used for runtime configuration of model
 31:  *
 32:  * @var array
 33:  */
 34:     public $runtime = array();
 35: 
 36: /**
 37:  * Stores the joinTable object for generating joins.
 38:  *
 39:  * @var object
 40:  */
 41:     protected $_joinTable;
 42: 
 43: /**
 44:  * Stores the runtime model for generating joins.
 45:  *
 46:  * @var Model
 47:  */
 48:     protected $_runtimeModel;
 49: 
 50: /**
 51:  * Callback
 52:  *
 53:  * $config for TranslateBehavior should be
 54:  * array('fields' => array('field_one',
 55:  * 'field_two' => 'FieldAssoc', 'field_three'))
 56:  *
 57:  * With above example only one permanent hasMany will be joined (for field_two
 58:  * as FieldAssoc)
 59:  *
 60:  * $config could be empty - and translations configured dynamically by
 61:  * bindTranslation() method
 62:  *
 63:  * @param Model $Model Model the behavior is being attached to.
 64:  * @param array $config Array of configuration information.
 65:  * @return mixed
 66:  */
 67:     public function setup(Model $Model, $config = array()) {
 68:         $db = ConnectionManager::getDataSource($Model->useDbConfig);
 69:         if (!$db->connected) {
 70:             trigger_error(
 71:                 __d('cake_dev', 'Datasource %s for TranslateBehavior of model %s is not connected', $Model->useDbConfig, $Model->alias),
 72:                 E_USER_ERROR
 73:             );
 74:             return false;
 75:         }
 76: 
 77:         $this->settings[$Model->alias] = array();
 78:         $this->runtime[$Model->alias] = array('fields' => array());
 79:         $this->translateModel($Model);
 80:         return $this->bindTranslation($Model, $config, false);
 81:     }
 82: 
 83: /**
 84:  * Cleanup Callback unbinds bound translations and deletes setting information.
 85:  *
 86:  * @param Model $Model Model being detached.
 87:  * @return void
 88:  */
 89:     public function cleanup(Model $Model) {
 90:         $this->unbindTranslation($Model);
 91:         unset($this->settings[$Model->alias]);
 92:         unset($this->runtime[$Model->alias]);
 93:     }
 94: 
 95: /**
 96:  * beforeFind Callback
 97:  *
 98:  * @param Model $Model Model find is being run on.
 99:  * @param array $query Array of Query parameters.
100:  * @return array Modified query
101:  */
102:     public function beforeFind(Model $Model, $query) {
103:         $this->runtime[$Model->alias]['virtualFields'] = $Model->virtualFields;
104:         $locale = $this->_getLocale($Model);
105:         if (empty($locale)) {
106:             return $query;
107:         }
108:         $db = $Model->getDataSource();
109:         $RuntimeModel = $this->translateModel($Model);
110: 
111:         if (!empty($RuntimeModel->tablePrefix)) {
112:             $tablePrefix = $RuntimeModel->tablePrefix;
113:         } else {
114:             $tablePrefix = $db->config['prefix'];
115:         }
116:         $joinTable = new StdClass();
117:         $joinTable->tablePrefix = $tablePrefix;
118:         $joinTable->table = $RuntimeModel->table;
119:         $joinTable->schemaName = $RuntimeModel->getDataSource()->getSchemaName();
120: 
121:         $this->_joinTable = $joinTable;
122:         $this->_runtimeModel = $RuntimeModel;
123: 
124:         if (is_string($query['fields']) && $query['fields'] === "COUNT(*) AS {$db->name('count')}") {
125:             $query['fields'] = "COUNT(DISTINCT({$db->name($Model->escapeField())})) {$db->alias}count";
126:             $query['joins'][] = array(
127:                 'type' => 'INNER',
128:                 'alias' => $RuntimeModel->alias,
129:                 'table' => $joinTable,
130:                 'conditions' => array(
131:                     $Model->escapeField() => $db->identifier($RuntimeModel->escapeField('foreign_key')),
132:                     $RuntimeModel->escapeField('model') => $Model->name,
133:                     $RuntimeModel->escapeField('locale') => $locale
134:                 )
135:             );
136:             $conditionFields = $this->_checkConditions($Model, $query);
137:             foreach ($conditionFields as $field) {
138:                 $query = $this->_addJoin($Model, $query, $field, $field, $locale);
139:             }
140:             unset($this->_joinTable, $this->_runtimeModel);
141:             return $query;
142:         } elseif (is_string($query['fields'])) {
143:             $query['fields'] = String::tokenize($query['fields']);
144:         }
145: 
146:         $fields = array_merge(
147:             $this->settings[$Model->alias],
148:             $this->runtime[$Model->alias]['fields']
149:         );
150:         $addFields = array();
151:         if (empty($query['fields'])) {
152:             $addFields = $fields;
153:         } elseif (is_array($query['fields'])) {
154:             $isAllFields = (
155:                 in_array($Model->alias . '.' . '*', $query['fields']) ||
156:                 in_array($Model->escapeField('*'), $query['fields'])
157:             );
158:             foreach ($fields as $key => $value) {
159:                 $field = (is_numeric($key)) ? $value : $key;
160:                 if ($isAllFields ||
161:                     in_array($Model->alias . '.' . $field, $query['fields']) ||
162:                     in_array($field, $query['fields'])
163:                 ) {
164:                     $addFields[] = $field;
165:                 }
166:             }
167:         }
168: 
169:         $this->runtime[$Model->alias]['virtualFields'] = $Model->virtualFields;
170:         if ($addFields) {
171:             foreach ($addFields as $_f => $field) {
172:                 $aliasField = is_numeric($_f) ? $field : $_f;
173: 
174:                 foreach (array($aliasField, $Model->alias . '.' . $aliasField) as $_field) {
175:                     $key = array_search($_field, (array)$query['fields']);
176: 
177:                     if ($key !== false) {
178:                         unset($query['fields'][$key]);
179:                     }
180:                 }
181:                 $query = $this->_addJoin($Model, $query, $field, $aliasField, $locale);
182:             }
183:         }
184:         $this->runtime[$Model->alias]['beforeFind'] = $addFields;
185:         unset($this->_joinTable, $this->_runtimeModel);
186:         return $query;
187:     }
188: 
189: /**
190:  * Check a query's conditions for translated fields.
191:  * Return an array of translated fields found in the conditions.
192:  *
193:  * @param Model $Model The model being read.
194:  * @param array $query The query array.
195:  * @return array The list of translated fields that are in the conditions.
196:  */
197:     protected function _checkConditions(Model $Model, $query) {
198:         $conditionFields = array();
199:         if (empty($query['conditions']) || (!empty($query['conditions']) && !is_array($query['conditions']))) {
200:             return $conditionFields;
201:         }
202:         foreach ($query['conditions'] as $col => $val) {
203:             foreach ($this->settings[$Model->alias] as $field => $assoc) {
204:                 if (is_numeric($field)) {
205:                     $field = $assoc;
206:                 }
207:                 if (strpos($col, $field) !== false) {
208:                     $conditionFields[] = $field;
209:                 }
210:             }
211:         }
212:         return $conditionFields;
213:     }
214: 
215: /**
216:  * Appends a join for translated fields.
217:  *
218:  * @param Model $Model The model being worked on.
219:  * @param array $query The query array to append a join to.
220:  * @param string $field The field name being joined.
221:  * @param string $aliasField The aliased field name being joined.
222:  * @param string|array $locale The locale(s) having joins added.
223:  * @return array The modified query
224:  */
225:     protected function _addJoin(Model $Model, $query, $field, $aliasField, $locale) {
226:         $db = ConnectionManager::getDataSource($Model->useDbConfig);
227:         $RuntimeModel = $this->_runtimeModel;
228:         $joinTable = $this->_joinTable;
229:         $aliasVirtual = "i18n_{$field}";
230:         $alias = "I18n__{$field}";
231:         if (is_array($locale)) {
232:             foreach ($locale as $_locale) {
233:                 $aliasVirtualLocale = "{$aliasVirtual}_{$_locale}";
234:                 $aliasLocale = "{$alias}__{$_locale}";
235:                 $Model->virtualFields[$aliasVirtualLocale] = "{$aliasLocale}.content";
236:                 if (!empty($query['fields']) && is_array($query['fields'])) {
237:                     $query['fields'][] = $aliasVirtualLocale;
238:                 }
239:                 $query['joins'][] = array(
240:                     'type' => 'LEFT',
241:                     'alias' => $aliasLocale,
242:                     'table' => $joinTable,
243:                     'conditions' => array(
244:                         $Model->escapeField() => $db->identifier("{$aliasLocale}.foreign_key"),
245:                         "{$aliasLocale}.model" => $Model->name,
246:                         "{$aliasLocale}.{$RuntimeModel->displayField}" => $aliasField,
247:                         "{$aliasLocale}.locale" => $_locale
248:                     )
249:                 );
250:             }
251:         } else {
252:             $Model->virtualFields[$aliasVirtual] = "{$alias}.content";
253:             if (!empty($query['fields']) && is_array($query['fields'])) {
254:                 $query['fields'][] = $aliasVirtual;
255:             }
256:             $query['joins'][] = array(
257:                 'type' => 'INNER',
258:                 'alias' => $alias,
259:                 'table' => $joinTable,
260:                 'conditions' => array(
261:                     "{$Model->alias}.{$Model->primaryKey}" => $db->identifier("{$alias}.foreign_key"),
262:                     "{$alias}.model" => $Model->name,
263:                     "{$alias}.{$RuntimeModel->displayField}" => $aliasField,
264:                     "{$alias}.locale" => $locale
265:                 )
266:             );
267:         }
268:         return $query;
269:     }
270: 
271: /**
272:  * afterFind Callback
273:  *
274:  * @param Model $Model Model find was run on
275:  * @param array $results Array of model results.
276:  * @param bool $primary Did the find originate on $model.
277:  * @return array Modified results
278:  */
279:     public function afterFind(Model $Model, $results, $primary = false) {
280:         $Model->virtualFields = $this->runtime[$Model->alias]['virtualFields'];
281: 
282:         $this->runtime[$Model->alias]['virtualFields'] = $this->runtime[$Model->alias]['fields'] = array();
283:         if (!empty($this->runtime[$Model->alias]['restoreFields'])) {
284:             $this->runtime[$Model->alias]['fields'] = $this->runtime[$Model->alias]['restoreFields'];
285:             unset($this->runtime[$Model->alias]['restoreFields']);
286:         }
287: 
288:         $locale = $this->_getLocale($Model);
289: 
290:         if (empty($locale) || empty($results) || empty($this->runtime[$Model->alias]['beforeFind'])) {
291:             return $results;
292:         }
293:         $beforeFind = $this->runtime[$Model->alias]['beforeFind'];
294: 
295:         foreach ($results as $key => &$row) {
296:             $results[$key][$Model->alias]['locale'] = (is_array($locale)) ? current($locale) : $locale;
297:             foreach ($beforeFind as $_f => $field) {
298:                 $aliasField = is_numeric($_f) ? $field : $_f;
299:                 $aliasVirtual = "i18n_{$field}";
300:                 if (is_array($locale)) {
301:                     foreach ($locale as $_locale) {
302:                         $aliasVirtualLocale = "{$aliasVirtual}_{$_locale}";
303:                         if (!isset($row[$Model->alias][$aliasField]) && !empty($row[$Model->alias][$aliasVirtualLocale])) {
304:                             $row[$Model->alias][$aliasField] = $row[$Model->alias][$aliasVirtualLocale];
305:                             $row[$Model->alias]['locale'] = $_locale;
306:                         }
307:                         unset($row[$Model->alias][$aliasVirtualLocale]);
308:                     }
309: 
310:                     if (!isset($row[$Model->alias][$aliasField])) {
311:                         $row[$Model->alias][$aliasField] = '';
312:                     }
313:                 } else {
314:                     $value = '';
315:                     if (isset($row[$Model->alias][$aliasVirtual])) {
316:                         $value = $row[$Model->alias][$aliasVirtual];
317:                     }
318:                     $row[$Model->alias][$aliasField] = $value;
319:                     unset($row[$Model->alias][$aliasVirtual]);
320:                 }
321:             }
322:         }
323:         return $results;
324:     }
325: 
326: /**
327:  * beforeValidate Callback
328:  *
329:  * @param Model $Model Model invalidFields was called on.
330:  * @param array $options Options passed from Model::save().
331:  * @return bool
332:  * @see Model::save()
333:  */
334:     public function beforeValidate(Model $Model, $options = array()) {
335:         unset($this->runtime[$Model->alias]['beforeSave']);
336:         $this->_setRuntimeData($Model);
337:         return true;
338:     }
339: 
340: /**
341:  * beforeSave callback.
342:  *
343:  * Copies data into the runtime property when `$options['validate']` is
344:  * disabled. Or the runtime data hasn't been set yet.
345:  *
346:  * @param Model $Model Model save was called on.
347:  * @param array $options Options passed from Model::save().
348:  * @return bool true.
349:  * @see Model::save()
350:  */
351:     public function beforeSave(Model $Model, $options = array()) {
352:         if (isset($options['validate']) && !$options['validate']) {
353:             unset($this->runtime[$Model->alias]['beforeSave']);
354:         }
355:         if (isset($this->runtime[$Model->alias]['beforeSave'])) {
356:             return true;
357:         }
358:         $this->_setRuntimeData($Model);
359:         return true;
360:     }
361: 
362: /**
363:  * Sets the runtime data.
364:  *
365:  * Used from beforeValidate() and beforeSave() for compatibility issues,
366:  * and to allow translations to be persisted even when validation
367:  * is disabled.
368:  *
369:  * @param Model $Model Model using this behavior.
370:  * @return void
371:  */
372:     protected function _setRuntimeData(Model $Model) {
373:         $locale = $this->_getLocale($Model);
374:         if (empty($locale)) {
375:             return true;
376:         }
377:         $fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']);
378:         $tempData = array();
379: 
380:         foreach ($fields as $key => $value) {
381:             $field = (is_numeric($key)) ? $value : $key;
382: 
383:             if (isset($Model->data[$Model->alias][$field])) {
384:                 $tempData[$field] = $Model->data[$Model->alias][$field];
385:                 if (is_array($Model->data[$Model->alias][$field])) {
386:                     if (is_string($locale) && !empty($Model->data[$Model->alias][$field][$locale])) {
387:                         $Model->data[$Model->alias][$field] = $Model->data[$Model->alias][$field][$locale];
388:                     } else {
389:                         $values = array_values($Model->data[$Model->alias][$field]);
390:                         $Model->data[$Model->alias][$field] = $values[0];
391:                     }
392:                 }
393:             }
394:         }
395:         $this->runtime[$Model->alias]['beforeSave'] = $tempData;
396:     }
397: 
398: /**
399:  * Restores model data to the original data.
400:  * This solves issues with saveAssociated and validate = first.
401:  *
402:  * @param Model $Model Model using this behavior.
403:  * @return void
404:  */
405:     public function afterValidate(Model $Model) {
406:         $Model->data[$Model->alias] = array_merge(
407:             $Model->data[$Model->alias],
408:             $this->runtime[$Model->alias]['beforeSave']
409:         );
410:         return true;
411:     }
412: 
413: /**
414:  * afterSave Callback
415:  *
416:  * @param Model $Model Model the callback is called on
417:  * @param bool $created Whether or not the save created a record.
418:  * @param array $options Options passed from Model::save().
419:  * @return void
420:  */
421:     public function afterSave(Model $Model, $created, $options = array()) {
422:         if (!isset($this->runtime[$Model->alias]['beforeValidate']) && !isset($this->runtime[$Model->alias]['beforeSave'])) {
423:             return true;
424:         }
425:         if (isset($this->runtime[$Model->alias]['beforeValidate'])) {
426:             $tempData = $this->runtime[$Model->alias]['beforeValidate'];
427:         } else {
428:             $tempData = $this->runtime[$Model->alias]['beforeSave'];
429:         }
430: 
431:         unset($this->runtime[$Model->alias]['beforeValidate'], $this->runtime[$Model->alias]['beforeSave']);
432:         $conditions = array('model' => $Model->name, 'foreign_key' => $Model->id);
433:         $RuntimeModel = $this->translateModel($Model);
434: 
435:         if ($created) {
436:             $tempData = $this->_prepareTranslations($Model, $tempData);
437:         }
438:         $locale = $this->_getLocale($Model);
439:         $atomic = array();
440:         if (isset($options['atomic'])) {
441:             $atomic = array('atomic' => $options['atomic']);
442:         }
443: 
444:         foreach ($tempData as $field => $value) {
445:             unset($conditions['content']);
446:             $conditions['field'] = $field;
447:             if (is_array($value)) {
448:                 $conditions['locale'] = array_keys($value);
449:             } else {
450:                 $conditions['locale'] = $locale;
451:                 if (is_array($locale)) {
452:                     $value = array($locale[0] => $value);
453:                 } else {
454:                     $value = array($locale => $value);
455:                 }
456:             }
457:             $translations = $RuntimeModel->find('list', array(
458:                 'conditions' => $conditions,
459:                 'fields' => array(
460:                     $RuntimeModel->alias . '.locale',
461:                     $RuntimeModel->alias . '.id'
462:                 )
463:             ));
464:             foreach ($value as $_locale => $_value) {
465:                 $RuntimeModel->create();
466:                 $conditions['locale'] = $_locale;
467:                 $conditions['content'] = $_value;
468:                 if (array_key_exists($_locale, $translations)) {
469:                     $RuntimeModel->save(array(
470:                         $RuntimeModel->alias => array_merge(
471:                             $conditions, array('id' => $translations[$_locale])
472:                         ),
473:                         $atomic
474:                     ));
475:                 } else {
476:                     $RuntimeModel->save(array($RuntimeModel->alias => $conditions), $atomic);
477:                 }
478:             }
479:         }
480:     }
481: 
482: /**
483:  * Prepares the data to be saved for translated records.
484:  * Add blank fields, and populates data for multi-locale saves.
485:  *
486:  * @param Model $Model Model using this behavior
487:  * @param array $data The sparse data that was provided.
488:  * @return array The fully populated data to save.
489:  */
490:     protected function _prepareTranslations(Model $Model, $data) {
491:         $fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']);
492:         $locales = array();
493:         foreach ($data as $key => $value) {
494:             if (is_array($value)) {
495:                 $locales = array_merge($locales, array_keys($value));
496:             }
497:         }
498:         $locales = array_unique($locales);
499:         $hasLocales = count($locales) > 0;
500: 
501:         foreach ($fields as $key => $field) {
502:             if (!is_numeric($key)) {
503:                 $field = $key;
504:             }
505:             if ($hasLocales && !isset($data[$field])) {
506:                 $data[$field] = array_fill_keys($locales, '');
507:             } elseif (!isset($data[$field])) {
508:                 $data[$field] = '';
509:             }
510:         }
511:         return $data;
512:     }
513: 
514: /**
515:  * afterDelete Callback
516:  *
517:  * @param Model $Model Model the callback was run on.
518:  * @return void
519:  */
520:     public function afterDelete(Model $Model) {
521:         $RuntimeModel = $this->translateModel($Model);
522:         $conditions = array('model' => $Model->name, 'foreign_key' => $Model->id);
523:         $RuntimeModel->deleteAll($conditions);
524:     }
525: 
526: /**
527:  * Get selected locale for model
528:  *
529:  * @param Model $Model Model the locale needs to be set/get on.
530:  * @return mixed string or false
531:  */
532:     protected function _getLocale(Model $Model) {
533:         if (!isset($Model->locale) || $Model->locale === null) {
534:             $I18n = I18n::getInstance();
535:             $I18n->l10n->get(Configure::read('Config.language'));
536:             $Model->locale = $I18n->l10n->locale;
537:         }
538: 
539:         return $Model->locale;
540:     }
541: 
542: /**
543:  * Get instance of model for translations.
544:  *
545:  * If the model has a translateModel property set, this will be used as the class
546:  * name to find/use. If no translateModel property is found 'I18nModel' will be used.
547:  *
548:  * @param Model $Model Model to get a translatemodel for.
549:  * @return Model
550:  */
551:     public function translateModel(Model $Model) {
552:         if (!isset($this->runtime[$Model->alias]['model'])) {
553:             if (!isset($Model->translateModel) || empty($Model->translateModel)) {
554:                 $className = 'I18nModel';
555:             } else {
556:                 $className = $Model->translateModel;
557:             }
558: 
559:             $this->runtime[$Model->alias]['model'] = ClassRegistry::init($className);
560:         }
561:         if (!empty($Model->translateTable) && $Model->translateTable !== $this->runtime[$Model->alias]['model']->useTable) {
562:             $this->runtime[$Model->alias]['model']->setSource($Model->translateTable);
563:         } elseif (empty($Model->translateTable) && empty($Model->translateModel)) {
564:             $this->runtime[$Model->alias]['model']->setSource('i18n');
565:         }
566:         return $this->runtime[$Model->alias]['model'];
567:     }
568: 
569: /**
570:  * Bind translation for fields, optionally with hasMany association for
571:  * fake field.
572:  *
573:  * *Note* You should avoid binding translations that overlap existing model properties.
574:  * This can cause un-expected and un-desirable behavior.
575:  *
576:  * @param Model $Model using this behavior of model
577:  * @param string|array $fields string with field or array(field1, field2=>AssocName, field3)
578:  * @param bool $reset Leave true to have the fields only modified for the next operation.
579:  *   if false the field will be added for all future queries.
580:  * @return bool
581:  * @throws CakeException when attempting to bind a translating called name. This is not allowed
582:  *   as it shadows Model::$name.
583:  */
584:     public function bindTranslation(Model $Model, $fields, $reset = true) {
585:         if (is_string($fields)) {
586:             $fields = array($fields);
587:         }
588:         $associations = array();
589:         $RuntimeModel = $this->translateModel($Model);
590:         $default = array(
591:             'className' => $RuntimeModel->alias,
592:             'foreignKey' => 'foreign_key',
593:             'order' => 'id'
594:         );
595: 
596:         foreach ($fields as $key => $value) {
597:             if (is_numeric($key)) {
598:                 $field = $value;
599:                 $association = null;
600:             } else {
601:                 $field = $key;
602:                 $association = $value;
603:             }
604:             if ($association === 'name') {
605:                 throw new CakeException(
606:                     __d('cake_dev', 'You cannot bind a translation named "name".')
607:                 );
608:             }
609:             $this->_removeField($Model, $field);
610: 
611:             if ($association === null) {
612:                 if ($reset) {
613:                     $this->runtime[$Model->alias]['fields'][] = $field;
614:                 } else {
615:                     $this->settings[$Model->alias][] = $field;
616:                 }
617:             } else {
618:                 if ($reset) {
619:                     $this->runtime[$Model->alias]['fields'][$field] = $association;
620:                     $this->runtime[$Model->alias]['restoreFields'][] = $field;
621:                 } else {
622:                     $this->settings[$Model->alias][$field] = $association;
623:                 }
624: 
625:                 foreach (array('hasOne', 'hasMany', 'belongsTo', 'hasAndBelongsToMany') as $type) {
626:                     if (isset($Model->{$type}[$association]) || isset($Model->__backAssociation[$type][$association])) {
627:                         trigger_error(
628:                             __d('cake_dev', 'Association %s is already bound to model %s', $association, $Model->alias),
629:                             E_USER_ERROR
630:                         );
631:                         return false;
632:                     }
633:                 }
634:                 $associations[$association] = array_merge($default, array('conditions' => array(
635:                     'model' => $Model->name,
636:                     $RuntimeModel->displayField => $field
637:                 )));
638:             }
639:         }
640: 
641:         if (!empty($associations)) {
642:             $Model->bindModel(array('hasMany' => $associations), $reset);
643:         }
644:         return true;
645:     }
646: 
647: /**
648:  * Update runtime setting for a given field.
649:  *
650:  * @param Model $Model Model using this behavior
651:  * @param string $field The field to update.
652:  * @return void
653:  */
654:     protected function _removeField(Model $Model, $field) {
655:         if (array_key_exists($field, $this->settings[$Model->alias])) {
656:             unset($this->settings[$Model->alias][$field]);
657:         } elseif (in_array($field, $this->settings[$Model->alias])) {
658:             $this->settings[$Model->alias] = array_merge(array_diff($this->settings[$Model->alias], array($field)));
659:         }
660: 
661:         if (array_key_exists($field, $this->runtime[$Model->alias]['fields'])) {
662:             unset($this->runtime[$Model->alias]['fields'][$field]);
663:         } elseif (in_array($field, $this->runtime[$Model->alias]['fields'])) {
664:             $this->runtime[$Model->alias]['fields'] = array_merge(array_diff($this->runtime[$Model->alias]['fields'], array($field)));
665:         }
666:     }
667: 
668: /**
669:  * Unbind translation for fields, optionally unbinds hasMany association for
670:  * fake field
671:  *
672:  * @param Model $Model using this behavior of model
673:  * @param string|array $fields string with field, or array(field1, field2=>AssocName, field3), or null for
674:  *    unbind all original translations
675:  * @return bool
676:  */
677:     public function unbindTranslation(Model $Model, $fields = null) {
678:         if (empty($fields) && empty($this->settings[$Model->alias])) {
679:             return false;
680:         }
681:         if (empty($fields)) {
682:             return $this->unbindTranslation($Model, $this->settings[$Model->alias]);
683:         }
684: 
685:         if (is_string($fields)) {
686:             $fields = array($fields);
687:         }
688:         $associations = array();
689: 
690:         foreach ($fields as $key => $value) {
691:             if (is_numeric($key)) {
692:                 $field = $value;
693:                 $association = null;
694:             } else {
695:                 $field = $key;
696:                 $association = $value;
697:             }
698: 
699:             $this->_removeField($Model, $field);
700: 
701:             if ($association !== null && (isset($Model->hasMany[$association]) || isset($Model->__backAssociation['hasMany'][$association]))) {
702:                 $associations[] = $association;
703:             }
704:         }
705: 
706:         if (!empty($associations)) {
707:             $Model->unbindModel(array('hasMany' => $associations), false);
708:         }
709:         return true;
710:     }
711: 
712: }
713: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs