PageRenderTime 54ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/class.atkcontroller.inc

https://github.com/ibuildingsnl/ATK
PHP | 853 lines | 536 code | 70 blank | 247 comment | 58 complexity | 6a1aedb6d958cd0db73f03ca31fb59e1 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, LGPL-3.0
  1. <?php
  2. /**
  3. * This file is part of the Achievo ATK distribution.
  4. * Detailed copyright and licensing information can be found
  5. * in the doc/COPYRIGHT and doc/LICENSE files which should be
  6. * included in the distribution.
  7. *
  8. * @package atk
  9. *
  10. * @copyright (c)2000-2004 Ibuildings.nl BV
  11. * @license http://www.achievo.org/atk/licensing ATK Open Source License
  12. *
  13. * @version $Revision$
  14. */
  15. /**
  16. * The atkController class
  17. *
  18. * @author Maurice Maas <maurice@ibuildings.nl>
  19. * @package atk
  20. * @todo Make this class a real singleton.
  21. */
  22. class atkController
  23. {
  24. /**
  25. * The name of the wizard.
  26. * @access protected
  27. * @var String
  28. */
  29. var $m_name;
  30. /**
  31. * The module of the wizard.
  32. * @access protected
  33. * @var String
  34. */
  35. var $m_module_name;
  36. /**
  37. * Reference to the instance of currently selected atkNode
  38. *
  39. * @var unknown_type
  40. */
  41. var $m_node = NULL;
  42. /**
  43. * The postvars in this pageload
  44. *
  45. * @var array Key/value
  46. */
  47. var $m_postvars = NULL;
  48. /**
  49. * The file to use when creating url's
  50. *
  51. * @var string filename
  52. */
  53. var $m_php_file = "";
  54. /**
  55. * By this property is determined if the output of the
  56. * handleRequest method should be returned as a string
  57. * or the output should be outputted by atkOutput.
  58. *
  59. * @var unknown_type
  60. */
  61. var $m_return_output = false;
  62. /**
  63. * Key/value Array containing which are be send als post or get vars
  64. * @access private
  65. * @var Array
  66. */
  67. var $m_hidden_vars = array();
  68. /**
  69. * Constructor of atkController
  70. *
  71. * @return atkController object
  72. */
  73. function atkController()
  74. {
  75. global $g_sessionManager;
  76. if(is_object($g_sessionManager))
  77. {
  78. $atkControllerClass = $g_sessionManager->stackVar("atkcontroller");
  79. //Its not so nice to use the getNodeModule and getNodeType functions,
  80. //because the name suggests they work with atkNodes. But they also do
  81. //the job when using other class names.
  82. $this->m_name = getNodeType($atkControllerClass);
  83. $this->m_module_name = getNodeModule($atkControllerClass);
  84. }
  85. }
  86. /**
  87. * Create instance of controller (determined by class variable) if not yet created, return instance of atkcontroller
  88. *
  89. * @access private
  90. * @param string $class
  91. * @param boolean $replace
  92. * @return instance of controller
  93. */
  94. function &_instance($class="", $replace=false)
  95. {
  96. static $s_object=NULL;
  97. if(!is_object($s_object) || $replace)
  98. {
  99. global $ATK_VARS;
  100. if (empty($class) && isset($ATK_VARS['atkcontroller']))
  101. $class = $ATK_VARS['atkcontroller'];
  102. if (empty($class))
  103. $class = "atk.atkcontroller";
  104. //We save the controller in stack, so the controller constructor
  105. //can store the Controller name and module. It is also saved for other
  106. //atk levels if we move down the stack.
  107. global $g_sessionManager;
  108. if(is_object($g_sessionManager))
  109. {
  110. $g_sessionManager->stackVar("atkcontroller", $class);
  111. }
  112. $s_object = atknew($class);
  113. }
  114. return $s_object;
  115. }
  116. /**
  117. * Return the one and only instance of the class
  118. *
  119. * @return atkController
  120. */
  121. function &getInstance()
  122. {
  123. $object = &atkcontroller::_instance();
  124. return $object;
  125. }
  126. /**
  127. * Return the one and only instance of the class
  128. *
  129. * @param string $controller The class of the controller to instanciate
  130. * @return object
  131. */
  132. function &createInstance($controller)
  133. {
  134. atkdebug("atkcontroller::createInstance() ".$controller);
  135. //First check if another controller is active. If so make sure this
  136. //controller will use atkOutput to return output
  137. $currentController = atkController::getInstance();
  138. if(is_object($currentController))
  139. $currentController->setReturnOutput(true);
  140. //Now create new controller
  141. $controller = &atkController::_instance($controller, true);
  142. return $controller;
  143. }
  144. /**
  145. * This is the wrapper method for all http requests on a node.
  146. *
  147. * The method looks at the atkaction from the postvars and determines what
  148. * should be done. If possible, it instantiates actionHandlers for
  149. * handling the actual action.
  150. *
  151. * @param array $postvars The request variables for the node.
  152. * @param string $flags Render flags (see class atkPage).
  153. *
  154. */
  155. function handleRequest($postvars, $flags=NULL)
  156. {
  157. // we set the m_postvars variable of the controller for backwards compatibility reasons (when using $obj->dispatch in the dispatch.php)
  158. $this->m_postvars = $postvars;
  159. $node = &$this->getNode();
  160. $node->m_postvars = $postvars;
  161. if(!is_object($node) || !method_exists($node,'getUi')) return "";
  162. $page = &$node->getPage();
  163. // backwards compatibility mode
  164. if ($flags == NULL)
  165. {
  166. $flags = array_key_exists("atkpartial", $postvars) ? HTML_PARTIAL : HTML_STRICT;
  167. }
  168. elseif (is_bool($flags))
  169. {
  170. $flags = $flags ? HTML_STRICT : HTML_HEADER|HTML_DOCTYPE;
  171. }
  172. // Use invoke to be backwards compatible with overrides
  173. // of loadDispatchPage in atknode.
  174. $this->invoke("loadDispatchPage", $postvars);
  175. $screen = '';
  176. if (!$page->isEmpty() || hasFlag($flags, HTML_PARTIAL)) // Only output an html output if there is anything to output.
  177. {
  178. $screen = $page->render(null, $flags);
  179. }
  180. if(!$this->m_return_output)
  181. {
  182. $output = &atkOutput::getInstance();
  183. $output->output($screen);
  184. }
  185. // This is the end of all things for this page..
  186. // so we clean up some resources..
  187. $db = &$node->getDb();
  188. if (is_object($db)) $db->disconnect();
  189. atkdebug("disconnected from the database");
  190. if($this->m_return_output)
  191. {
  192. return $screen;
  193. }
  194. return "";
  195. }
  196. /**
  197. * Return the html title for the content frame. Default we show node name and action.
  198. */
  199. protected function getHtmlTitle()
  200. {
  201. $node = &$this->getNode();
  202. $ui = &$node->getUi();
  203. return atktext('app_shorttitle')." - ".$ui->title($node->m_module, $node->m_type,$node->m_postvars['atkaction']);
  204. }
  205. /**
  206. * This method is a wrapper for calling the node dispatch function
  207. * Therefore each node can define it's own dispatch function
  208. * The default dispatch function of the atkNode will call the handleRequest function of the controller
  209. *
  210. * @param array $postvars
  211. * @param integer $flags
  212. */
  213. function dispatch($postvars, $flags=NULL)
  214. {
  215. $this->m_postvars = $postvars;
  216. $node = &$this->getNode();
  217. return $node->dispatch($postvars, $flags);
  218. }
  219. /**
  220. * Set m_node variable of this class
  221. *
  222. * @param object $node
  223. */
  224. function setNode(&$node)
  225. {
  226. $this->m_node = &$node;
  227. }
  228. /**
  229. * Get m_node variable or if not set make instance of atkNode class (determined by using the postvars)
  230. *
  231. * @return reference to atknode
  232. */
  233. function &getNode()
  234. {
  235. if(is_object($this->m_node))
  236. {
  237. return $this->m_node;
  238. }
  239. else
  240. {
  241. //if the object not yet exists, try to create it
  242. $fullclassname = $this->m_postvars["atknodetype"];
  243. if(isset($fullclassname) && $fullclassname != null)
  244. {
  245. $this->m_node = &getNode($fullclassname);
  246. if (is_object($this->m_node))
  247. {
  248. return $this->m_node;
  249. }
  250. else
  251. {
  252. global $ATK_VARS;
  253. atkError("No object '".$ATK_VARS["atknodetype"]."' created!!?!");
  254. }
  255. }
  256. }
  257. $res = NULL;
  258. return $res; // prevent notice
  259. }
  260. /**
  261. * Does the actual loading of the dispatch page
  262. * And adds it to the page for the dispatch() method to render.
  263. * @param array $postvars The request variables for the node.
  264. */
  265. function loadDispatchPage($postvars)
  266. {
  267. $this->m_postvars = $postvars;
  268. $node = &$this->getNode();
  269. if(!is_object($node)) return;
  270. $node->m_postvars = $postvars;
  271. $node->m_action = $postvars['atkaction'];
  272. if (isset($postvars["atkpartial"]))
  273. {
  274. $node->m_partial = $postvars["atkpartial"];
  275. }
  276. $page = &$node->getPage();
  277. $page->setTitle(atktext('app_shorttitle')." - ".$this->getUi()->title($node->m_module, $node->m_type, $node->m_action));
  278. if ($node->allowed($node->m_action))
  279. {
  280. $secMgr = &atkGetSecurityManager();
  281. $secMgr->logAction($node->m_type, $node->m_action);
  282. $node->callHandler($node->m_action);
  283. if (is_array($node->m_postvars["atkselector"])) {
  284. $atkSelectorDecoded = array();
  285. foreach ($node->m_postvars["atkselector"] as $rowIndex => $selector) {
  286. list($selector, $pk) = explode("=", $selector);
  287. $atkSelectorDecoded[] = $pk;
  288. $id = implode(',', $atkSelectorDecoded);
  289. }
  290. } else {
  291. list($selector,$id) = explode("=", atkarraynvl($node->m_postvars, "atkselector", "="));
  292. }
  293. $page->register_hiddenvars(array("atknodetype"=>$node->m_module.".".$node->m_type, "atkselector"=>str_replace("'", "", $id)));
  294. }
  295. else
  296. {
  297. $page->addContent($this->accessDeniedPage());
  298. }
  299. }
  300. /**
  301. * Render a generic access denied page.
  302. *
  303. * @return String A complete html page with generic access denied message.
  304. */
  305. function accessDeniedPage()
  306. {
  307. $node = &$this->getNode();
  308. $content = "<br><br>".atktext("error_node_action_access_denied", "", $node->m_type)."<br><br><br>";
  309. // Add a cancel button to an error page if it is a dialog.
  310. if ($node->m_partial == 'dialog')
  311. $content.= $this->getDialogButton('cancel', 'close');
  312. return $this->genericPage(atktext('access_denied'), $content);
  313. }
  314. /**
  315. * Render a generic page, with a box, title, stacktrace etc.
  316. * @param String $title The pagetitle and if $content is a string, also
  317. * the boxtitle.
  318. * @param mixed $content The content to display on the page. This can be:
  319. * - A string which will be the content of a single
  320. * box on the page.
  321. * - An associative array of $boxtitle=>$boxcontent
  322. * pairs. Each pair will be rendered as a seperate
  323. * box.
  324. * @return String A complete html page with the desired content.
  325. */
  326. function genericPage($title, $content)
  327. {
  328. $node = &$this->getNode();
  329. $ui = &$node->getUi();
  330. $node->addStyle("style.css");
  331. if (!is_array($content)) $content = array($title=>$content);
  332. $blocks = array();
  333. foreach($content as $itemtitle => $itemcontent)
  334. {
  335. if ($node->m_partial == 'dialog')
  336. $blocks[] = $ui->renderDialog(array("title"=>$itemtitle, "content"=>$itemcontent));
  337. else
  338. $blocks[] = $ui->renderBox(array("title"=>$itemtitle, "content"=>$itemcontent), 'dispatch');
  339. }
  340. /**
  341. * @todo Don't use renderActionPage here because it tries to determine
  342. * it's own title based on the title which is passed as action.
  343. * Instead use something like the commented line below:
  344. */
  345. //return $ui->render("actionpage.tpl", array("blocks"=>$blocks, "title"=>$title));
  346. return $this->renderActionPage($title, $blocks);
  347. }
  348. /**
  349. * Render a generic action.
  350. *
  351. * Renders actionpage.tpl for the desired action. This includes the
  352. * given block(s) and a pagetrial, but not a box.
  353. * @param String $action The action for which the page is rendered.
  354. * @param mixed $blocks Pieces of html content to be rendered. Can be a
  355. * single string with content, or an array with
  356. * multiple content blocks.
  357. * @return String Piece of HTML containing the given blocks and a pagetrail.
  358. */
  359. function renderActionPage($action, $blocks=array())
  360. {
  361. if(!is_array($blocks))
  362. {
  363. $blocks = ($blocks==""?array():array($blocks));
  364. }
  365. $node = &$this->getNode();
  366. $ui = &$node->getUi();
  367. // todo: overridable action templates
  368. return $ui->render("actionpage.tpl", array("blocks"=>$blocks,
  369. "title"=>$this->actionPageTitle()));
  370. }
  371. /**
  372. * Return the title to be show on top of an Action Page
  373. *
  374. * @return string The title
  375. */
  376. function actionPageTitle()
  377. {
  378. $node = &$this->getNode();
  379. $ui = &$node->getUi();
  380. return $ui->title($node->m_module, $node->m_type);
  381. }
  382. /**
  383. * Determine the url for the feedbackpage.
  384. *
  385. * Output is dependent on the feedback configuration. If feedback is not
  386. * enabled for the action, this method returns an empty string, so the
  387. * result of this method can be passed directly to the redirect() method
  388. * after completing the action.
  389. *
  390. * The $record parameter is ignored by the default implementation, but
  391. * derived classes may override this method to perform record-specific
  392. * feedback.
  393. * @param String $action The action that was performed
  394. * @param int $status The status of the action.
  395. * @param array $record The record on which the action was performed.
  396. * @param String $message An optional message to pass to the feedbackpage,
  397. * for example to explain the reason why an action
  398. * failed.
  399. * @param integer $levelskip The number of levels to skip
  400. * @return String The feedback url.
  401. */
  402. function feedbackUrl($action, $status, $record="", $message="", $levelskip=null)
  403. {
  404. $node = &$this->getNode();
  405. if((isset($node->m_feedback[$action]) && hasFlag($node->m_feedback[$action], $status)) || $status==ACTION_FAILED)
  406. {
  407. $vars = array("atkaction"=>"feedback", "atkfbaction"=>$action, "atkactionstatus"=>$status,"atkfbmessage"=>$message);
  408. $atkNodeType = $node->atkNodeType();
  409. $sessionStatus = SESSION_REPLACE;
  410. // The level skip given is based on where we should end up after the
  411. // feedback action is shown to the user. This means that the feedback
  412. // action should be shown one level higher in the stack, hence the -1.
  413. // Default the feedback action is shown on the current level, so in that
  414. // case we have a simple SESSION_REPLACE with a level skip of null.
  415. $levelskip = $levelskip == null ? null : $levelskip - 1;
  416. }
  417. else
  418. {
  419. // Default we leave atkNodeType empty because the sessionmanager will determine which is de atkNodeType
  420. $vars = array();
  421. $atkNodeType = "";
  422. $sessionStatus = SESSION_BACK;
  423. }
  424. return (session_url($this->dispatchUrl($vars, $atkNodeType), $sessionStatus, $levelskip));
  425. }
  426. /**
  427. * Generate a dispatch menu URL for use with nodes
  428. * and their specific actions.
  429. * @param string $params: A key/value array with extra options for the url
  430. * @param string $atknodetype The atknodetype (modulename.nodename)
  431. * @param string $file The php file to use for dispatching, defaults to dispatch.php
  432. * @return string url for the node with the action
  433. */
  434. function dispatchUrl($params=array(), $atknodetype="", $file="")
  435. {
  436. if (!is_array($params)) $params = array();
  437. $vars = array_merge($params, $this->m_hidden_vars);
  438. if($file!="") $phpfile = $file;
  439. else $phpfile = $this->getPhpFile();
  440. // When $atknodetype is empty this means that we use the atknodetype from session
  441. $dispatch_url = dispatch_url($atknodetype, atkArrayNvl($vars, "atkaction", ""), $vars, $phpfile);
  442. return $dispatch_url;
  443. }
  444. /**
  445. * Returns the form buttons for a certain page.
  446. *
  447. * Can be overridden by derived classes to define custom buttons.
  448. * @param String $mode The action for which the buttons are retrieved.
  449. * @param array $record The record currently displayed/edited in the form.
  450. * This param can be used to define record specific
  451. * buttons.
  452. */
  453. function getFormButtons($mode, $record)
  454. {
  455. $result = array();
  456. $node = &$this->getNode();
  457. $page = &$node->getPage();
  458. $page->register_script(atkconfig("atkroot")."atk/javascript/tools.js");
  459. // edit mode
  460. if ($mode == "edit")
  461. {
  462. // if atklevel is 0 or less, we are at the bottom of the session stack,
  463. // which means that 'saveandclose' doesn't close anyway, so we leave out
  464. // the 'saveandclose' and 'cancel' button. Unless, a feedback screen is configured.
  465. if (atkLevel() >0 || hasFlag(atkArrayNvl($node->m_feedback, "update", 0), ACTION_SUCCESS))
  466. {
  467. $result[] = $this->getButton('saveandclose', true);
  468. }
  469. $result[] = $this->getButton('save');
  470. if (atkLevel() >0 || hasFlag(atkArrayNvl($node->m_feedback, "update", 0), ACTION_SUCCESS))
  471. {
  472. $result[] = $this->getButton('cancel');
  473. }
  474. }
  475. elseif ($mode == "add")
  476. {
  477. if($node->hasFlag(NF_EDITAFTERADD) === true && $node->allowed('edit'))
  478. {
  479. $result[] = $this->getButton('saveandedit', true);
  480. }
  481. else
  482. {
  483. if($node->hasFlag(NF_EDITAFTERADD) === true)
  484. {
  485. atkwarning("NF_EDITAFTERADD found but no 'edit' privilege.");
  486. }
  487. $result[] = $this->getButton('saveandclose', true);
  488. }
  489. // if action is admin, we don't show the cancelbutton or the add next button
  490. if ($node->hasFlag(NF_ADDAFTERADD) && !$node->hasFlag(NF_EDITAFTERADD))
  491. $result[] = $this->getButton('saveandnext', false);
  492. $result[] = $this->getButton('cancel');
  493. }
  494. elseif ($mode == "view")
  495. {
  496. if(atkLevel() > 0)
  497. $result[] = $this->getButton('back');
  498. // if appropriate, display an edit button.
  499. if (!$node->hasFlag(NF_NO_EDIT)&&$node->allowed("edit", $record))
  500. {
  501. $result[] = '<input type="hidden" name="atkaction" value="edit">'.
  502. '<input type="hidden" name="atknodetype" value="'.$node->atkNodeType().'">'.
  503. '&nbsp;'.$this->getButton('edit').'&nbsp;';
  504. }
  505. }
  506. elseif ($mode == "delete")
  507. {
  508. $result[] = '<input name="confirm" type="submit" class="btn_ok" value="'.$node->text('yes').'">';
  509. $result[] = '<input name="cancel" type="submit" class="btn_cancel" value="'.$node->text('no').'">';
  510. }
  511. return $result;
  512. }
  513. /**
  514. * Create a button.
  515. *
  516. * @param String $action
  517. * @param Bool $default Add the atkdefaultbutton class?
  518. * @return HTML
  519. */
  520. function getButton($action, $default=false, $label=null)
  521. {
  522. $name = "";
  523. $class = "";
  524. switch ($action)
  525. {
  526. case "save":
  527. $name = "atknoclose";
  528. $class = "btn_save";
  529. break;
  530. case "saveandclose":
  531. $name = "atksaveandclose";
  532. $class = "btn_saveandclose";
  533. break;
  534. case "cancel":
  535. $name = "atkcancel";
  536. $class = "btn_cancel";
  537. break;
  538. case "saveandedit":
  539. $name = "atksaveandcontinue";
  540. $class = "btn_saveandcontinue";
  541. break;
  542. case "saveandnext":
  543. $name = "atksaveandnext";
  544. $class = "btn_saveandnext";
  545. break;
  546. case "back":
  547. $name = "atkback";
  548. $class = "btn_cancel";
  549. $value = '<< '.atktext($action, 'atk');
  550. break;
  551. case "edit":
  552. $name = "atkedit";
  553. $class = "btn_save";
  554. break;
  555. default:
  556. $name = $action;
  557. $class = "atkbutton";
  558. }
  559. if (!isset($value))
  560. $value = $this->m_node->text($action);
  561. if (isset($label))
  562. $value = $label;
  563. $value = atk_htmlentities($value);
  564. if ($default)
  565. $class .= (!empty($class) ? ' ' : '').'atkdefaultbutton';
  566. if ($class != "")
  567. $class = "class=\"$class\" ";
  568. if ($name != "")
  569. $name = "name=\"".$this->m_node->getEditFieldPrefix()."{$name}\" ";
  570. return '<button type="submit" '.$class.$name.'>'.$value.'</button>';
  571. }
  572. /**
  573. * Create a dialog button.
  574. *
  575. * @param String $action The action ('save' or 'cancel')
  576. * @param String $label The label for this button
  577. * @param String $url
  578. * @param array $extraParams
  579. * @return HTML
  580. */
  581. function getDialogButton($action, $label=null, $url=null, $extraParams=array())
  582. {
  583. atkimport('atk.ui.atkdialog');
  584. // Disable the button when clicked to prevent javascript errors.
  585. $onClick = 'this.disabled=\'true\';';
  586. switch($action)
  587. {
  588. case "save":
  589. $class = "btn_save";
  590. $onClick.= atkDialog::getSaveCall($url, 'dialogform', $extraParams);
  591. break;
  592. case "cancel":
  593. $class = "btn_cancel";
  594. $onClick.= atkDialog::getCloseCall();
  595. break;
  596. default:
  597. return "";
  598. }
  599. $label = $label == null ? atktext($action, 'atk') : $label;
  600. return '<input type="button" class="'.$class.'" name="'.$label.'" value="'.$label.'" onClick="'.$onClick.'" />';
  601. }
  602. /**
  603. * Set Key/value pair in m_hidden_vars array. Saved pairs are
  604. * send as post or get vars in the next page load
  605. *
  606. * @param string $name the reference key
  607. * @param string $value the actual value
  608. */
  609. function setHiddenVar($name, $value)
  610. {
  611. $this->m_hidden_vars[$name] = $value;
  612. }
  613. /**
  614. * Return m_hidden_vars array.
  615. *
  616. * @return array
  617. */
  618. function getHiddenVars()
  619. {
  620. return $this->m_hidden_vars;
  621. }
  622. /**
  623. * Set php_file member variable
  624. *
  625. * @param string $phpfile
  626. */
  627. function setPhpFile($phpfile)
  628. {
  629. $this->m_php_file = $phpfile;
  630. }
  631. /**
  632. * Return php_file. If not set, returns theme-level dispatchfile, if not set either, return (sanitized) PHP_SELF
  633. *
  634. * @return string The name of the file to which subsequent requests should be posted.
  635. */
  636. function getPhpFile()
  637. {
  638. $theme = &atkinstance('atk.ui.atktheme');
  639. if ($this->m_php_file != "") return $this->m_php_file;
  640. return $theme->getAttribute('dispatcher', atkconfig("dispatcher", atkSelf()));
  641. }
  642. /**
  643. * Return m_hidden_vars as html input types.
  644. *
  645. * @return string
  646. */
  647. function getHiddenVarsString()
  648. {
  649. if (count($this->m_hidden_vars) == 0) return "";
  650. foreach($this->m_hidden_vars as $hiddenVarName => $hiddenVarValue)
  651. {
  652. $varString .= '<input type="hidden" name="'.$hiddenVarName.'" value="'.$hiddenVarValue.'">';
  653. }
  654. return $varString;
  655. }
  656. /**
  657. * Configure if you want the html returned or leave it up to atkOutput.
  658. *
  659. * @param bool $returnOutput
  660. */
  661. function setReturnOutput($returnOutput)
  662. {
  663. $this->m_return_output = $returnOutput;
  664. }
  665. /**
  666. * Return the setting for returning output
  667. *
  668. * @return bool
  669. */
  670. function getReturnOutput()
  671. {
  672. return $this->m_return_output;
  673. }
  674. /**
  675. * Return a reference to the atkPage object. This object
  676. * is used to render output as an html page.
  677. *
  678. * @return object reference
  679. */
  680. function &getPage()
  681. {
  682. $page = &atkinstance("atk.ui.atkpage");
  683. return $page;
  684. }
  685. /**
  686. * Get the ui instance for drawing and templating purposes.
  687. *
  688. * @return atkUi An atkUi instance for drawing and templating.
  689. */
  690. function &getUi()
  691. {
  692. $ui = &atkinstance("atk.ui.atkui");
  693. return $ui;
  694. }
  695. /**
  696. * Generic method invoker (copied from class.atkactionhandler.inc).
  697. *
  698. * Controller methods invoked with invoke() instead of directly, have a major
  699. * advantage: the controller automatically searches for an override in the
  700. * node. For example, If a controller calls its getSomething() method using
  701. * the invoke method, the node may implement its own version of
  702. * getSomething() and that method will then be called instead of the
  703. * original. The controller is passed by reference to the override function
  704. * as first parameter, so if necessary, you can call the original method
  705. * from inside the override.
  706. *
  707. * The function accepts a variable number of parameters. Any parameter
  708. * that you would pass to the method, can be passed to invoke(), and
  709. * invoke() will pass the parameters on to the method.
  710. *
  711. * There is one limitation: you can't pass parameters by reference if
  712. * you use invoke().
  713. *
  714. * <b>Example:</b>
  715. *
  716. * <code>
  717. * $controller->invoke("dispatch", $postvars, $fullpage);
  718. * </code>
  719. *
  720. * This will call dispatch(&$handler, $postvars, $flags) on your node class
  721. * if present, or dispatch($postvars, $flags) in the handler if the node has
  722. * no override.
  723. *
  724. * @param String $methodname The name of the method to call.
  725. * @return mixed The method returns the return value of the invoked
  726. * method.
  727. */
  728. function invoke($methodname)
  729. {
  730. $arguments = func_get_args(); // Put arguments in a variable (php won't let us pass func_get_args() to other functions directly.
  731. // the first argument is $methodname, which we already defined by name.
  732. array_shift($arguments);
  733. $node = &$this->getNode();
  734. if ($node!==NULL && method_exists($node, $methodname))
  735. {
  736. atkdebug("atkcontroller::invoke() Invoking '$methodname' override on node");
  737. // We pass the original object as last parameter to the override.
  738. array_push($arguments, $this);
  739. return call_user_func_array(array(&$node, $methodname), $arguments);
  740. }
  741. else if (method_exists($this, $methodname))
  742. {
  743. atkdebug("atkcontroller::invoke() Invoking '$methodname' on controller");
  744. return call_user_func_array(array(&$this, $methodname), $arguments);
  745. }
  746. atkerror("atkcontroller::invoke() Undefined method '$methodname' in atkController");
  747. }
  748. /**
  749. * Return module name of controller
  750. *
  751. * @return string module name
  752. */
  753. function getModuleName()
  754. {
  755. return $this->m_module_name;
  756. }
  757. /**
  758. * Return controller name
  759. *
  760. * @return string controller name
  761. */
  762. function getName()
  763. {
  764. return $this->m_name;
  765. }
  766. }
  767. ?>