Jose Diaz-Gonzalez is a developer living in New York City. He currently works at SeatGeek

About

Toggle Behavior

UPDATE: Fixed link to latest revision of ToggleBehavior

There is apparently already something out there that does this, but here is my "ToggleBehavior". Does not really do callbacks, but it works well otherwise. I'll try to fix the callbacks sometime soon.

It's a study on how to build a usable feature in CakePHP, this time being a behavior. Each revision is stored on the CakePHP Bin, and you'll see a slow progression from something quick and dirty to a behavior that follows most CakePHP conventions. About the only convention not followed is the non-use of the Ternary Operator. I use it as I think it is neat, but you can make a new revision that doesn't.

Cheers if it works for you, and feedback is always welcome!

Original Bin

toggle.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?php
/**
 * Toggle Model Behavior
 * 
 * Allows you to toggle default fields or a specific field/fields
 * Can also toggle a field on or off explicitly
 *
 * @package app.models.behaviors
 * @author Jose Diaz-Gonzalez
 * @version 1.4.7
 **/
class ToggleBehavior extends ModelBehavior {
/**
 * Default settings for a model that has this behavior attached.
 *
 * @var array
 * @access protected
 */
  protected $_settings = array(
      'fields' => array('active'),
      'callbacks' => false
  );
/**
 * Initiate behaviour for the model using settings.
 *
 * @param AppModel $Model Model instance
 * @param array $config Settings to override for model.
 * @access public
 */
  function setup(&$model, $config = array()) {
      $this->settings[$model->alias] = $this->_settings;

      //merge custom config with default settings
      $this->settings[$model->alias] = array_merge($this->settings[$model->alias], (array)$config);
  }

/**
 * Toggles the fields
 *
 * @param AppModel $Model Model instance
 * @param mixed $id Optional The ID of the record to read
 * @param array $fieldNames name of fields to be toggled
 * @return mixed Array of non-existing fields, saved data/true if everything went well, or false if saving failed
 * @author Jose Diaz-Gonzalez
 **/
  function toggle(&$model, $fieldNames = array(), $id = null) {
      return $this->_turnFields($model, $fieldNames, 'toggle', $id);
  }

/**
 * Toggles the fields on
 * 
 * @param AppModel $Model Model instance
 * @param mixed $id Optional The ID of the record to read
 * @param array $fieldNames name of fields to be toggled
 * @return mixed Array of non-existing fields, saved data/true if everything went well, or false if saving failed
 * @author Jose Diaz-Gonzalez
 **/
  function turnOn(&$model, $fieldNames = array(), $id = null) {
      return $this->_turnFields($model, $fieldNames, 1, $id);
  }

/**
 * Toggles the fields off
 *
 * @param AppModel $Model Model instance
 * @param array $fieldNames name of fields to be toggled
 * @param mixed $id Optional The ID of the record to read
 * @return mixed Array of non-existing fields, saved data/true if everything went well, or false if saving failed
 * @author Jose Diaz-Gonzalez
 **/
  function turnOff(&$model, $fieldNames = array(), $id = null) {
      return $this->_turnFields($model, $fieldNames, 0, $id);
  }

/**
 * Does the grunt work for toggling
 *
 * @param AppModel $Model Model instance
 * @param array $fieldNames name of fields to be toggled
 * @param mixed $type Either the string "toggle" or the value to save
 * @param mixed $id Optional The ID of the record to read
 * @return mixed Array of non-existing fields, saved data/true if everything went well, or false if saving failed
 * @author Jose Diaz-Gonzalez
 **/
  function _turnFields(&$model, $fieldNames = array(), $type = null, $id = null) {
      if (!is_null($id) and !empty($id)) {
          $id;
      } else {
          if (is_array($this->id)) {
              $id = $this->id[0];
          } else {
              $id = $this->id;
          }
      }

      $errors = array();
      if (!empty($fields)) {
          $fields = $fieldNames;
     } else {
         $fields = $this->settings[$model->alias]['fields'];
     }
     $model->id = $id;

     $arr = $this->_checkFields($model, $fields);
     $errors = $arr['errors'];
     $fields = $arr['fields'];
     if (!empty($errors)) {var_dump($errors);die;
         return $errors;
     }

     switch ($type) {
         case 'toggle' :
             foreach ($fields as $field) {
                 $field = $model->escapeField($field);
                 $toSave[$field] = 'NOT ' . $field;
             }
             break;
         default:
             foreach ($fields as $field) {
                 $toSave[$field] = $type;
             }
             break;
     }
     
     if ($this->settings[$model->alias]['callbacks']) {
         $model->beforeSave();
         $data = $model->updateAll($toSave, array($model->escapeField() => $id));
         $model->afterSave();
         
     } else {
         $data = $model->updateAll($toSave, array($model->escapeField() => $id));
     }
     return $data;
 }

/**
 * Checks the model to ensure that the fields do indeed exist
 *
 * @param AppModel $Model Model instance
 * @param array $fieldNames name of fields to be toggled
 * @return array Fields and Errors in a single array
 * @author Jose Diaz-Gonzalez
 **/
 function _checkFields(&$model, $fields) {
     $errors = array();

     foreach ($fields as $key => $field) {
         if(!$model->hasField($field)) {
             unset($fields[$key]);
             $errors[] = $field;
         }
     }

     return array('fields' => $fields, 'errors' => $errors);
 }
}
?>
0 Responses. Add Yours!

Discussion

blog comments powered by Disqus