1: <?php
2:
3: App::uses('ModelTraverser', 'Base.Lib');
4:
5: class AssociationIntegrityBehavior extends ModelBehavior {
6:
7: public function beforeValidate(\Model $model, $options = array()) {
8: parent::beforeValidate($model, $options);
9: foreach ($model->belongsTo as $alias => $config) {
10: $this->__setupAssociationValidate($model, $alias, $config['foreignKey']);
11: $model->data[$model->alias][$config['foreignKey']] = $this->__currentFieldValue($model, $config['foreignKey']);
12: }
13: }
14:
15: public function beforeDelete(\Model $model, $cascade = true) {
16: $parentResult = parent::beforeDelete($model, $cascade);
17: if (!$parentResult) {
18: return $parentResult;
19: }
20: foreach ($model->hasMany as $alias => $config) {
21: if ($this->__hasHasManyAssociations($model, $alias)) {
22: return false;
23: }
24: }
25: return true;
26: }
27:
28: private function __hasHasManyAssociations(\Model $model, $alias) {
29: return $model->{$alias}->hasAny(array(
30: $alias . '.' . $model->hasMany[$alias]['foreignKey'] => $model->id
31: ));
32: }
33:
34: private function __currentFieldValue(\Model $model, $field) {
35: return ModelTraverser::_findField($model, $model->data, $field, false);
36: }
37:
38: private function __setupAssociationValidate(\Model $model, $alias, $foreignKey) {
39: if (empty($model->validate[$foreignKey][__CLASS__])) {
40: $model->validate[$foreignKey][__CLASS__] = $this->__foreignKeyValidation(
41: $model
42: , $alias
43: , $foreignKey
44: );
45: }
46: }
47:
48: private function __foreignKeyValidation(\Model $model, $associationAlias, $foreignKey) {
49: return array(
50: 'rule' => array('validateForeignKey', $associationAlias),
51: 'message' => 'Associação é vazia ou não existe',
52: 'allowEmpty' => $this->__allowEmpty($model, $foreignKey),
53: 'required' => true,
54: );
55: }
56:
57: private function __allowEmpty(\Model $model, $foreignKey) {
58: $schema = $model->schema();
59: return $schema[$foreignKey]['null'];
60: }
61:
62: public function validateForeignKey(\Model $model, $check, $associationAlias) {
63: foreach ($check as $field => $value) {
64: if (!$value) {
65: return false;
66: }
67: $key = $associationAlias . '.' . $model->{$associationAlias}->primaryKey;
68: $associationRow = $model->{$associationAlias}->find('first', array(
69: 'conditions' => array($key => $value),
70: 'recursive' => -1,
71: ));
72: if (empty($associationRow)) {
73: return false;
74: }
75: }
76: return true;
77: }
78:
79: }
80: