CRM_Core_BAO_Setting - Don't prefill settings
[civicrm-core.git] / CRM / Core / StateMachine.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
e7112fa7 6 | Copyright CiviCRM LLC (c) 2004-2015 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
e7112fa7 31 * @copyright CiviCRM LLC (c) 2004-2015
6a488035
TO
32 */
33
34/**
8eedd10a 35 * Core StateMachine.
6a488035 36 *
8eedd10a 37 * All state machines subclass for the core one for functionality specific to their needs.
6a488035 38 *
8eedd10a 39 * A state machine keeps track of different states and forms for a
40 * html quickform controller.
6a488035
TO
41 */
42class CRM_Core_StateMachine {
43
44 /**
f9e31d7f 45 * The controller of this state machine.
6a488035
TO
46 * @var object
47 */
48 protected $_controller;
49
50 /**
f9e31d7f 51 * The list of states that belong to this state machine.
6a488035
TO
52 * @var array
53 */
54 protected $_states;
55
56 /**
100fef9d 57 * The list of pages that belong to this state machine. Note
6a488035
TO
58 * that a state and a form have a 1 <-> 1 relationship. so u
59 * can always derive one from the other
60 * @var array
61 */
62 protected $_pages;
63
64 /**
f9e31d7f 65 * The names of the pages.
6a488035
TO
66 *
67 * @var array
68 */
69 protected $_pageNames;
70
71 /**
f9e31d7f 72 * The mode that the state machine is operating in.
6a488035
TO
73 * @var int
74 */
75 protected $_action = NULL;
76
77 /**
f9e31d7f 78 * The display name for this machine.
6a488035
TO
79 * @var string
80 */
81 protected $_name = NULL;
82
83 /**
f9e31d7f 84 * Class constructor.
6a488035 85 *
6a0b768e
TO
86 * @param object $controller
87 * The controller for this state machine.
6a488035 88 *
da3c7979 89 * @param \const|int $action
dd244018
EM
90 *
91 * @return \CRM_Core_StateMachine
6a488035 92 */
00be9182 93 public function __construct(&$controller, $action = CRM_Core_Action::NONE) {
6a488035
TO
94 $this->_controller = &$controller;
95 $this->_action = $action;
96
97 $this->_states = array();
98 }
99
100 /**
2e2605fe 101 * Getter for name.
6a488035
TO
102 *
103 * @return string
6a488035
TO
104 */
105 public function getName() {
106 return $this->_name;
107 }
108
109 /**
2e2605fe 110 * Setter for name.
6a488035 111 *
389bcebf 112 * @param string $name
6a488035
TO
113 */
114 public function setName($name) {
115 $this->_name = $name;
116 }
117
118 /**
2e2605fe
EM
119 * Do a state transition jump.
120 *
121 * Currently only supported types are
6a488035
TO
122 * Next and Back. The other actions (Cancel, Done, Submit etc) do
123 * not need the state machine to figure out where to go
124 *
6a0b768e
TO
125 * @param CRM_Core_Form $page
126 * The current form-page.
127 * @param string $actionName
128 * Current action name, as one Action object can serve multiple actions.
129 * @param string $type
130 * The type of transition being requested (Next or Back).
6a488035 131 *
8eedd10a 132 * @return object
6a488035 133 */
00be9182 134 public function perform(&$page, $actionName, $type = 'Next') {
6a488035
TO
135 // save the form values and validation status to the session
136 $page->isFormBuilt() or $page->buildForm();
137
138 $pageName = $page->getAttribute('name');
139 $data = &$page->controller->container();
140
141 $data['values'][$pageName] = $page->exportValues();
142 $data['valid'][$pageName] = $page->validate();
143
144 // if we are going to the next state
145 // Modal form and page is invalid: don't go further
146 if ($type == 'Next' && !$data['valid'][$pageName]) {
147 return $page->handle('display');
148 }
149
150 $state = &$this->_states[$pageName];
151
152 // dont know how or why we landed here so abort and display
153 // current page
154 if (empty($state)) {
155 return $page->handle('display');
156 }
157
158 // the page is valid, process it if we are jumping to the next state
159 if ($type == 'Next') {
e6a0a301 160 $page->mainProcess();
6a488035
TO
161 // we get the state again, since postProcess might have changed it
162 // this bug took me forever to find :) Lobo
163 $state = &$this->_states[$pageName];
164 $state->handleNextState($page);
165 }
166 else {
167 $state->handleBackState($page);
168 }
169 }
170
171 /**
2e2605fe 172 * Helper function to add a State to the state machine.
6a488035 173 *
6a0b768e
TO
174 * @param string $name
175 * The internal name.
176 * @param int $type
177 * The type of state (START|FINISH|SIMPLE).
178 * @param object $prev
179 * The previous page if any.
180 * @param object $next
181 * The next page if any.
6a488035 182 */
00be9182 183 public function addState($name, $type, $prev, $next) {
6a488035
TO
184 $this->_states[$name] = new CRM_Core_State($name, $type, $prev, $next, $this);
185 }
186
187 /**
2e2605fe 188 * Given a name find the corresponding state.
6a488035 189 *
6a0b768e
TO
190 * @param string $name
191 * The state name.
6a488035 192 *
a6c01b45
CW
193 * @return object
194 * the state object
6a488035 195 */
00be9182 196 public function find($name) {
6a488035
TO
197 if (array_key_exists($name, $this->_states)) {
198 return $this->_states[$name];
199 }
200 else {
201 return NULL;
202 }
203 }
204
205 /**
2e2605fe 206 * Return the list of state objects.
6a488035 207 *
a6c01b45
CW
208 * @return array
209 * array of states in the state machine
6a488035 210 */
00be9182 211 public function getStates() {
6a488035
TO
212 return $this->_states;
213 }
214
215 /**
f9e31d7f 216 * Return the state object corresponding to the name.
6a488035 217 *
6a0b768e
TO
218 * @param string $name
219 * Name of page.
6a488035 220 *
16b10e64
CW
221 * @return CRM_Core_State
222 * state object matching the name
6a488035 223 */
00be9182 224 public function &getState($name) {
6a488035 225 if (isset($this->_states[$name])) {
2aa397bc
TO
226 return $this->_states[$name];
227 }
6a488035
TO
228
229 /*
230 * This is a gross hack for ajax driven requests where
231 * we change the form name to allow multiple edits to happen
232 * We need a cleaner way of doing this going forward
233 */
481a74f4 234 foreach ($this->_states as $n => $s) {
6a488035
TO
235 if (substr($name, 0, strlen($n)) == $n) {
236 return $s;
237 }
238 }
239
2aa397bc 240 return NULL;
6a488035
TO
241 }
242
243 /**
f9e31d7f 244 * Return the list of form objects.
6a488035 245 *
a6c01b45
CW
246 * @return array
247 * array of pages in the state machine
6a488035 248 */
00be9182 249 public function getPages() {
6a488035
TO
250 return $this->_pages;
251 }
252
253 /**
2e2605fe 254 * Add sequential pages.
6a488035 255 *
2e2605fe 256 * Meta level function to create a simple wizard for a state machine that is completely sequential.
6a488035 257 *
6a0b768e
TO
258 * @param array $pages
259 * (reference ) the array of page objects.
6a488035 260 */
00be9182 261 public function addSequentialPages(&$pages) {
6a488035
TO
262 $this->_pages = &$pages;
263 $numPages = count($pages);
264
265 $this->_pageNames = array();
266 foreach ($pages as $tempName => $value) {
a7488080 267 if (!empty($value['className'])) {
6a488035
TO
268 $this->_pageNames[] = $tempName;
269 }
270 else {
271 $this->_pageNames[] = CRM_Utils_String::getClassName($tempName);
272 }
273 }
274
275 $i = 0;
276 foreach ($pages as $tempName => $value) {
277 $name = $this->_pageNames[$i];
278
279 $className = CRM_Utils_Array::value('className',
280 $value,
281 $tempName
282 );
283 $classPath = str_replace('_', '/', $className) . '.php';
284 if ($numPages == 1) {
285 $prev = $next = NULL;
286 $type = CRM_Core_State::START | CRM_Core_State::FINISH;
287 }
288 elseif ($i == 0) {
289 // start state
290 $prev = NULL;
291 $next = $this->_pageNames[$i + 1];
292 $type = CRM_Core_State::START;
293 }
294 elseif ($i == $numPages - 1) {
295 // finish state
296 $prev = $this->_pageNames[$i - 1];
297 $next = NULL;
298 $type = CRM_Core_State::FINISH;
299 }
300 else {
301 // in between simple state
302 $prev = $this->_pageNames[$i - 1];
303 $next = $this->_pageNames[$i + 1];
304 $type = CRM_Core_State::SIMPLE;
305 }
306
307 $this->addState($name, $type, $prev, $next);
308
309 $i++;
310 }
311 }
312
313 /**
f9e31d7f 314 * Reset the state machine.
6a488035 315 */
00be9182 316 public function reset() {
6a488035
TO
317 $this->_controller->reset();
318 }
319
320 /**
f9e31d7f 321 * Getter for action.
6a488035
TO
322 *
323 * @return int
6a488035 324 */
00be9182 325 public function getAction() {
6a488035
TO
326 return $this->_action;
327 }
328
329 /**
f9e31d7f 330 * Setter for content.
6a488035 331 *
6a0b768e
TO
332 * @param string $content
333 * The content generated by this state machine.
6a488035 334 */
00be9182 335 public function setContent(&$content) {
6a488035
TO
336 $this->_controller->setContent($content);
337 }
338
339 /**
f9e31d7f 340 * Getter for content.
6a488035
TO
341 *
342 * @return string
6a488035 343 */
00be9182 344 public function &getContent() {
6a488035
TO
345 return $this->_controller->getContent();
346 }
347
a0ee3941
EM
348 /**
349 * @return mixed
350 */
00be9182 351 public function getDestination() {
6a488035
TO
352 return $this->_controller->getDestination();
353 }
354
a0ee3941
EM
355 /**
356 * @return mixed
357 */
00be9182 358 public function getSkipRedirection() {
6a488035
TO
359 return $this->_controller->getSkipRedirection();
360 }
361
a0ee3941
EM
362 /**
363 * @return mixed
364 */
00be9182 365 public function fini() {
6a488035
TO
366 return $this->_controller->fini();
367 }
368
a0ee3941
EM
369 /**
370 * @return mixed
371 */
00be9182 372 public function cancelAction() {
6a488035
TO
373 return $this->_controller->cancelAction();
374 }
375
376 /**
377 * Should the controller reset the session
378 * In some cases, specifically search we want to remember
379 * state across various actions and want to go back to the
380 * beginning from the final state, but retain the same session
381 * values
382 *
389bcebf 383 * @return bool
6a488035 384 */
00be9182 385 public function shouldReset() {
6a488035 386 return TRUE;
2aa397bc 387 }
6a488035
TO
388
389}