00001 <?php
00002 require_once dirname(__FILE__) . '/commandbase.cls.php';
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 class CommandChain extends CommandBase {
00015
00016
00017
00018
00019
00020 protected $next = null;
00021
00022
00023
00024
00025
00026 protected $prev = null;
00027
00028
00029
00030
00031 public function can_execute($user) {
00032 $ret = $this->do_can_execute($user);
00033 if ($ret) {
00034 $next = $this->get_next();
00035 if ($next) {
00036 $ret = $next->can_execute($user);
00037 }
00038 }
00039 return $ret;
00040 }
00041
00042
00043
00044
00045
00046
00047 public function execute() {
00048 $ret = new Status();
00049
00050 DB::start_trans();
00051 try {
00052 $ret = $this->do_execute();
00053 if ($ret->is_ok()) {
00054 $next = $this->get_next();
00055 if ($next) {
00056 $ret = $next->execute();
00057 }
00058 }
00059 }
00060 catch (Exception $ex) {
00061 $ret->merge($ex);
00062 }
00063
00064 if ($ret->is_ok()) {
00065 $ret->merge(parent::execute());
00066 }
00067
00068 if ($ret->is_error()) {
00069 $this->undo();
00070 }
00071 DB::end_trans($ret);
00072
00073 return $ret;
00074 }
00075
00076
00077
00078
00079 public function undo() {
00080 $this->do_undo();
00081 $prev = $this->get_prev();
00082 if ($prev) {
00083 $prev->undo();
00084 }
00085 }
00086
00087
00088
00089
00090 protected function get_next() {
00091 return $this->next;
00092 }
00093
00094
00095
00096
00097 protected function get_prev() {
00098 return $this->prev;
00099 }
00100
00101
00102
00103
00104 public function append($cmd) {
00105 if ($this->next) {
00106 $this->next->append($cmd);
00107 }
00108 else {
00109 if ($cmd instanceof ICommand) {
00110 if ($cmd instanceof CommandChain) {
00111 $this->next = $cmd;
00112 $cmd->set_prev($this);
00113 }
00114 else {
00115 $adapter = new CommandChainAdapter($cmd);
00116 $this->append($adapter);
00117 }
00118 }
00119 }
00120 }
00121
00122
00123
00124
00125 public function append_array($commands) {
00126 if (is_array($commands)) {
00127 foreach($commands as $command) {
00128 $this->append($command);
00129 }
00130 }
00131 }
00132
00133
00134
00135
00136 protected function set_prev($cmd) {
00137 if ($cmd instanceof ICommand) {
00138 $this->prev = $cmd;
00139 }
00140 }
00141
00142
00143
00144
00145 protected function do_can_execute($user) {
00146 return parent::can_execute($user);
00147 }
00148
00149
00150
00151
00152 protected function do_execute() {
00153 return parent::execute();
00154 }
00155
00156
00157
00158
00159 protected function do_undo() {
00160 parent::undo();
00161 }
00162 }
00163
00164
00165
00166
00167 class CommandChainAdapter extends CommandChain {
00168
00169
00170
00171
00172
00173 protected $cmd = null;
00174
00175
00176
00177
00178
00179
00180 public function __construct($cmd) {
00181 if ($cmd instanceof ICommand) {
00182 $this->cmd = $cmd;
00183 }
00184 }
00185
00186
00187
00188
00189 protected function do_can_execute($user) {
00190 if ($this->cmd) {
00191 return $this->cmd->can_execute($user);
00192 }
00193 return parent::do_can_execute($user);
00194 }
00195
00196
00197
00198
00199 protected function do_execute() {
00200 if ($this->cmd) {
00201 return $this->cmd->execute();
00202 }
00203 return parent::do_execute();
00204 }
00205
00206
00207
00208
00209 protected function do_undo() {
00210 if ($this->cmd) {
00211 return $this->cmd->undo();
00212 }
00213 return parent::do_undo();
00214 }
00215 }
00216 ?>