Ensuring tests pass after bringing back support for db DSN connection. Rel. [501...
[akelos.git] / lib / AkActiveRecord / AkObserver.php
blob183d3b515f25bcd8d591fbe1cb80e5588f8cc850
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 // +----------------------------------------------------------------------+
5 // | Akelos Framework - http://www.akelos.org |
6 // +----------------------------------------------------------------------+
7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
8 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
9 // +----------------------------------------------------------------------+
11 /**
12 * @package ActiveRecord
13 * @subpackage Base
14 * @author Bermi Ferrer <bermi a.t akelos c.om>
15 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
16 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
19 require_once(AK_LIB_DIR.DS.'Ak.php');
20 require_once(AK_LIB_DIR.DS.'AkInflector.php');
21 require_once(AK_LIB_DIR.DS.'AkActiveRecord.php');
23 /**
24 * Observer classes respond to life-cycle callbacks to implement trigger-like
25 * behavior outside the original class. This is a great way to reduce the clutter
26 * that normally comes when the model class is burdened with functionality that
27 * doesn't pertain to the core responsibility of the class.
29 * Example:
31 * class CommentObserver extends AkObserver
32 * {
33 * function afterSave($comment)
34 * {
35 * Ak::mail("admin@example.com", "New comment was posted",
36 * $comment->toString());
37 * }
38 * }
40 * This Observer sends an email when a Comment::save is finished.
42 * ## Observing a class that can't be inferred
44 * Observers will by default be mapped to the class with which they share a name.
45 * So CommentObserver will be tied to observing Comment, ProductManagerObserver
46 * to ProductManager, and so on. If you want to name your observer differently
47 * than the class you're interested in observing, you can use the
48 * AkActiveRecord->observe() class method:
50 * function afterUpdate(&$account)
51 * {
52 * $AuditTrail =& new AuditTrail($account, "UPDATED");
53 * $AuditTrail->save();
54 * }
56 * If the audit observer needs to watch more than one kind of object, this can be
57 * specified with multiple arguments:
59 * function afterUpdate(&$record)
60 * {
61 * $ObservedRecord =& new AuditTrail($record, "UPDATED");
62 * $ObservedRecord->save();
63 * }
65 * The AuditObserver will now act on both updates to Account and Balance by
66 * treating them both as records.
68 * ## Available callback methods
70 * The observer can implement callback methods for each of these methods:
71 * beforeCreate, beforeValidation, beforeValidationOnCreate, beforeSave,
72 * afterValidation, afterValidationOnCreate, afterCreate and afterSave
74 * ## Triggering Observers
76 * In order to activate an observer, you need to call create an Observer instance
77 * and attach it to a model.
79 * In the Akelos Framework, this can be done in controllers using the short-hand
80 * of for example:
82 * $ComentObserverInstance =& new CommentObserver();
83 * $Model->addObserver(&$ComentObserverInstance);
86 class AkObserver extends AkObject
88 /**
89 * $_observing array of models that we're observing
91 var $_observing = array();
93 function __construct()
95 $num_args = func_num_args();
96 for ($i = 0; $i < $num_args; $i++){
97 $target = func_get_arg($i);
98 if(is_object($target)){
99 $this->observe(&$target);
100 }else{
101 $this->setObservedModels($target);
107 * Constructs the Observer
108 * @param $subject the name or names of the Models to observe
110 function observe (&$target)
112 static $memo;
113 $model_name = $target->getModelName();
114 $class_name = get_class($this);
115 if(empty($memo[$class_name]) || !in_array($model_name, $memo[$class_name])){
116 $memo[$class_name][] = $model_name;
117 $this->_observing[] = $model_name;
118 $target->addObserver(&$this);
123 * Constructs the Observer
124 * @param $subject the name or names of the Models to observe
126 function setObservedModels ()
128 $args = func_get_args();
129 $models = func_num_args() == 1 ? ( is_array($args[0]) ? $args[0] : array($args[0]) ) : $args;
131 foreach ($models as $class_name)
134 * @todo use Ak::import() instead.
136 $class_name = AkInflector::camelize($class_name);
137 if (!class_exists($class_name)){
138 require_once(AkInflector::toModelFilename($class_name));
140 $model =& new $class_name();
141 $this->observe(&$model);
146 function update($state = '')