PageRenderTime 73ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/e107_handlers/admin_ui.php

https://github.com/CasperGemini/e107
PHP | 5872 lines | 3529 code | 715 blank | 1628 comment | 486 complexity | 34ed6a3c5068ad414d571024b6ab9174 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. * e107 website system
  4. *
  5. * Copyright (C) 2008-2012 e107 Inc (e107.org)
  6. * Released under the terms and conditions of the
  7. * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
  8. *
  9. * Administration User Interface logic
  10. *
  11. * $URL$
  12. * $Id$
  13. */
  14. /**
  15. * @package e107
  16. * @subpackage e107_handlers
  17. * @version $Id$
  18. *
  19. * Administration User Interface logic
  20. */
  21. /**
  22. * @todo core request handler (non-admin), core response
  23. */
  24. if (!defined('e107_INIT')){ exit; }
  25. class e_admin_request
  26. {
  27. /**
  28. * Current GET request array
  29. * @var array
  30. */
  31. protected $_request_qry;
  32. /**
  33. * Current POST array
  34. * @var array
  35. */
  36. protected $_posted_qry;
  37. /**
  38. * Current Mode
  39. * @var string
  40. */
  41. protected $_mode = '';
  42. /**
  43. * Default Mode
  44. * @var string
  45. */
  46. protected $_default_mode = 'main';
  47. /**
  48. * Key name for mode search
  49. * @var string
  50. */
  51. protected $_mode_key = 'mode';
  52. /**
  53. * Current action
  54. * @var string
  55. */
  56. protected $_action = '';
  57. /**
  58. * Default Action
  59. * @var string
  60. */
  61. protected $_default_action = 'index';
  62. /**
  63. * Key name for action search
  64. * @var string
  65. */
  66. protected $_action_key = 'action';
  67. /**
  68. * Current ID
  69. * @var integer
  70. */
  71. protected $_id = 0;
  72. /**
  73. * Key name for ID search
  74. * @var string
  75. */
  76. protected $_id_key = 'id';
  77. /**
  78. * Constructor
  79. *
  80. * @param string|array $qry [optional]
  81. * @return none
  82. */
  83. public function __construct($request_string = null, $parse = true)
  84. {
  85. if(null === $request_string)
  86. {
  87. $request_string = str_replace('&amp;', '&', e_QUERY);
  88. }
  89. if($parse)
  90. {
  91. $this->parseRequest($request_string);
  92. }
  93. }
  94. /**
  95. * Parse request data
  96. * @param string|array $request_data
  97. * @return e_admin_request
  98. */
  99. protected function parseRequest($request_data)
  100. {
  101. if(is_string($request_data))
  102. {
  103. parse_str($request_data, $request_data);
  104. }
  105. $this->_request_qry = (array) $request_data;
  106. // Set current mode
  107. if(isset($this->_request_qry[$this->_mode_key]))
  108. {
  109. $this->_mode = preg_replace('/[^\w]/', '', $this->_request_qry[$this->_mode_key]);
  110. }
  111. // Set current action
  112. if(isset($this->_request_qry[$this->_action_key]))
  113. {
  114. $this->_action = preg_replace('/[^\w]/', '', $this->_request_qry[$this->_action_key]);
  115. }
  116. // Set current id
  117. if(isset($this->_request_qry[$this->_id_key]))
  118. {
  119. $this->_id = preg_replace('/[^\w-:.]/', '', $this->_request_qry[$this->_id_key]);
  120. }
  121. $this->_posted_qry =& $_POST; //raw?
  122. return $this;
  123. }
  124. /**
  125. * Retrieve variable from GET scope
  126. * If $key is null, all GET data will be returned
  127. *
  128. * @param string $key [optional]
  129. * @param mixed $default [optional]
  130. * @return mixed
  131. */
  132. public function getQuery($key = null, $default = null)
  133. {
  134. if(null === $key)
  135. {
  136. return $this->_request_qry;
  137. }
  138. return (isset($this->_request_qry[$key]) ? $this->_request_qry[$key] : $default);
  139. }
  140. /**
  141. * Set/Unset GET variable
  142. * If $key is array, $value is not used.
  143. * If $value is null, (string) $key is unset
  144. *
  145. * @param string|array $key
  146. * @param mixed $value [optional]
  147. * @return e_admin_request
  148. */
  149. public function setQuery($key, $value = null)
  150. {
  151. if(is_array($key))
  152. {
  153. foreach ($key as $k=>$v)
  154. {
  155. $this->setQuery($k, $v);
  156. }
  157. return $this;
  158. }
  159. if(null === $value)
  160. {
  161. unset($this->_request_qry[$key]);
  162. unset($_GET[$key]);
  163. return $this;
  164. }
  165. $this->_request_qry[$key] = $value;
  166. $_GET[$key] = $value;
  167. return $this;
  168. }
  169. /**
  170. * Retrieve variable from POST scope
  171. * If $key is null, all POST data will be returned
  172. *
  173. * @param string $key [optional]
  174. * @param mixed $default [optional]
  175. * @return mixed
  176. */
  177. public function getPosted($key = null, $default = null)
  178. {
  179. if(null === $key)
  180. {
  181. return $this->_posted_qry;
  182. }
  183. return (isset($this->_posted_qry[$key]) ? $this->_posted_qry[$key] : $default);
  184. }
  185. /**
  186. * Set/Unset POST variable
  187. * If $key is array, $value is not used.
  188. * If $value is null, (string) $key is unset
  189. *
  190. * @param object $key
  191. * @param object $value [optional]
  192. * @return e_admin_request
  193. */
  194. public function setPosted($key, $value = null)
  195. {
  196. if(is_array($key))
  197. {
  198. if(empty($key))
  199. {
  200. $this->_posted_qry = array(); //POST reset
  201. return $this;
  202. }
  203. foreach ($key as $k=>$v)
  204. {
  205. $this->setPosted($k, $v);
  206. }
  207. return $this;
  208. }
  209. if(null === $value)
  210. {
  211. unset($this->_posted_qry[$key]);
  212. return $this;
  213. }
  214. $tp = e107::getParser();
  215. $this->_posted_qry[$tp->post_toForm($key)] = $tp->post_toForm($value);
  216. return $this;
  217. }
  218. /**
  219. * Get current mode
  220. * @return string
  221. */
  222. public function getMode()
  223. {
  224. if(!$this->_mode) return $this->getDefaultMode();
  225. return $this->_mode;
  226. }
  227. /**
  228. * Get default mode
  229. * @return string
  230. */
  231. public function getDefaultMode()
  232. {
  233. return $this->_default_mode;
  234. }
  235. /**
  236. * Get current mode name
  237. *
  238. * @return string
  239. */
  240. public function getModeName()
  241. {
  242. return strtolower(str_replace('-', '_', $this->getMode()));
  243. }
  244. /**
  245. * Reset current mode
  246. * @param string $mode
  247. * @return e_admin_request
  248. */
  249. public function setMode($mode)
  250. {
  251. $this->_mode = preg_replace('/[^\w]/', '', $mode);
  252. $this->setQuery($this->_mode_key, $this->_mode);
  253. return $this;
  254. }
  255. /**
  256. * Set default mode
  257. * @param string $mode
  258. * @return e_admin_request
  259. */
  260. public function setDefaultMode($mode)
  261. {
  262. if($mode) $this->_default_mode = $mode;
  263. return $this;
  264. }
  265. /**
  266. * Set mode key name
  267. * @param string $key
  268. * @return e_admin_request
  269. */
  270. public function setModeKey($key)
  271. {
  272. $this->_mode_key = $key;
  273. return $this;
  274. }
  275. /**
  276. * Get current action
  277. * @return TBD
  278. */
  279. public function getAction()
  280. {
  281. if(!$this->_action) return $this->getDefaultAction();
  282. return $this->_action;
  283. }
  284. /**
  285. * Get default action
  286. * @return string
  287. */
  288. public function getDefaultAction()
  289. {
  290. return $this->_default_action;
  291. }
  292. /**
  293. * Get current action name
  294. * @return string camelized action
  295. */
  296. public function getActionName()
  297. {
  298. return $this->camelize($this->getAction());
  299. }
  300. /**
  301. * Reset current action
  302. *
  303. * @param string $action
  304. * @return e_admin_request
  305. */
  306. public function setAction($action)
  307. {
  308. $this->_action = preg_replace('/[^\w]/', '', $action);
  309. $this->setQuery($this->_action_key, $this->_action);
  310. return $this;
  311. }
  312. /**
  313. * Set default action
  314. *
  315. * @param string $action
  316. * @return e_admin_request
  317. */
  318. public function setDefaultAction($action)
  319. {
  320. if($action) $this->_default_action = $action;
  321. return $this;
  322. }
  323. /**
  324. * Set action key name
  325. * @param string $key
  326. * @return e_admin_request
  327. */
  328. public function setActionKey($key)
  329. {
  330. $this->_action_key = $key;
  331. return $this;
  332. }
  333. /**
  334. * Get current ID
  335. * @return integer
  336. */
  337. public function getId()
  338. {
  339. return $this->_id;
  340. }
  341. /**
  342. * Reset current ID
  343. * @param string $id
  344. * @return e_admin_request
  345. */
  346. public function setId($id)
  347. {
  348. $id = intval($id);
  349. $this->_id = $id;
  350. $this->setQuery($this->_id_key, $id);
  351. return $this;
  352. }
  353. /**
  354. * Set id key name
  355. * @param string $key
  356. * @return e_admin_request
  357. */
  358. public function setIdKey($key)
  359. {
  360. $this->_id_key = $key;
  361. return $this;
  362. }
  363. /**
  364. * Build query string from current request array
  365. * NOTE: changing url separator to &amp; ($encode==true) (thus URL XHTML compliance) works in PHP 5.1.2+ environment
  366. *
  367. * @param string|array $merge_with [optional] override request values
  368. * @param boolean $encode if true &amp; separator will be used, all values will be http encoded, default true
  369. * @param string|array $exclude_from_query numeric array/comma separated list of vars to be excluded from current query, true - don't use current query at all
  370. * @param boolean $keepSpecial don't exclude special vars as 'mode' and 'action'
  371. * @return string url encoded query string
  372. */
  373. public function buildQueryString($merge_with = array(), $encode = true, $exclude_from_query = '', $keepSpecial = true)
  374. {
  375. $ret = $this->getQuery();
  376. //special case - exclude all current
  377. if(true === $exclude_from_query)
  378. {
  379. $exclude_from_query = array_keys($ret);
  380. }
  381. // to array
  382. if(is_string($exclude_from_query))
  383. {
  384. $exclude_from_query = array_map('trim', explode(',', $exclude_from_query));
  385. }
  386. if($exclude_from_query)
  387. {
  388. foreach ($exclude_from_query as $var)
  389. {
  390. if($keepSpecial && $var != $this->_action_key && $var != $this->_mode_key) unset($ret[$var]);
  391. }
  392. }
  393. if(is_string($merge_with))
  394. {
  395. parse_str($merge_with, $merge_with);
  396. }
  397. $ret = array_merge($ret, (array) $merge_with);
  398. $separator = '&';
  399. if($encode)
  400. {
  401. $separator = '&amp;';
  402. //$ret = array_map('rawurlencode', $ret);
  403. }
  404. $ret = http_build_query($ret, 'numeric_', $separator);
  405. if(!$encode)
  406. {
  407. return rawurldecode($ret);
  408. }
  409. return $ret;
  410. }
  411. /**
  412. * Convert string to CamelCase
  413. *
  414. * @param string $str
  415. * @return string
  416. */
  417. public function camelize($str)
  418. {
  419. return implode('', array_map('ucfirst', explode('-', str_replace('_', '-', $str))));
  420. }
  421. }
  422. /**
  423. * TODO - front response parent, should do all the header.php work
  424. */
  425. class e_admin_response
  426. {
  427. /**
  428. * Body segments
  429. *
  430. * @var array
  431. */
  432. protected $_body = array();
  433. /**
  434. * Title segments
  435. *
  436. * @var unknown_type
  437. */
  438. protected $_title = array();
  439. /**
  440. * e107 meta title
  441. *
  442. * @var array
  443. */
  444. protected $_e_PAGETITLE = array();
  445. /**
  446. * e107 meta description
  447. *
  448. * @var array
  449. */
  450. protected $_META_DESCRIPTION = array();
  451. /**
  452. * e107 meta keywords
  453. *
  454. * @var array
  455. */
  456. protected $_META_KEYWORDS = array();
  457. /**
  458. * Render mods
  459. *
  460. * @var array
  461. */
  462. protected $_render_mod = array();
  463. /**
  464. * Meta title segment description
  465. *
  466. * @var string
  467. */
  468. protected $_meta_title_separator = ' - ';
  469. /**
  470. * Title segment separator
  471. *
  472. * @var string
  473. */
  474. protected $_title_separator = ' &raquo; ';
  475. /**
  476. * Constructor
  477. *
  478. */
  479. public function __construct()
  480. {
  481. $this->_render_mod['default'] = 'admin_page';
  482. }
  483. /**
  484. * Set body segments for a namespace
  485. *
  486. * @param string $content
  487. * @param string $namespace segment namesapce
  488. * @return e_admin_response
  489. */
  490. function setBody($content, $namespace = 'default')
  491. {
  492. $this->_body[$namespace] = $content;
  493. return $this;
  494. }
  495. /**
  496. * Append body segment to a namespace
  497. *
  498. * @param string $content
  499. * @param string $namespace segment namesapce
  500. * @return e_admin_response
  501. */
  502. function appendBody($content, $namespace = 'default')
  503. {
  504. if(!isset($this->_body[$namespace]))
  505. {
  506. $this->_body[$namespace] = array();
  507. }
  508. $this->_body[$namespace][] = $content;
  509. return $this;
  510. }
  511. /**
  512. * Prepend body segment to a namespace
  513. *
  514. * @param string $content
  515. * @param string $namespace segment namespace
  516. * @return e_admin_response
  517. */
  518. function prependBody($content, $namespace = 'default')
  519. {
  520. if(!isset($this->_body[$namespace]))
  521. {
  522. $this->_body[$namespace] = array();
  523. }
  524. $this->_body[$namespace] = array_merge(array($content), $this->_body[$namespace]);
  525. return $this;
  526. }
  527. /**
  528. * Get body segments from a namespace
  529. *
  530. * @param string $namespace segment namesapce
  531. * @param boolean $reset reset segment namespace
  532. * @param string|boolean $glue if false return array, else return string
  533. * @return string|array
  534. */
  535. function getBody($namespace = 'default', $reset = false, $glue = '')
  536. {
  537. $content = vartrue($this->_body[$namespace], array());
  538. if($reset)
  539. {
  540. $this->_body[$namespace] = array();
  541. }
  542. if(is_bool($glue))
  543. {
  544. return ($glue ? $content : implode('', $content));
  545. }
  546. return implode($glue, $content);
  547. }
  548. /**
  549. * Set title segments for a namespace
  550. *
  551. * @param string $title
  552. * @param string $namespace
  553. * @return e_admin_response
  554. */
  555. function setTitle($title, $namespace = 'default')
  556. {
  557. $this->_title[$namespace] = array($title);
  558. return $this;
  559. }
  560. /**
  561. * Append title segment to a namespace
  562. *
  563. * @param string $title
  564. * @param string $namespace segment namesapce
  565. * @return e_admin_response
  566. */
  567. function appendTitle($title, $namespace = 'default')
  568. {
  569. if(empty($title))
  570. {
  571. return $this;
  572. }
  573. if(!isset($this->_title[$namespace]))
  574. {
  575. $this->_title[$namespace] = array();
  576. }
  577. $this->_title[$namespace][] = $title;
  578. return $this;
  579. }
  580. /**
  581. * Prepend title segment to a namespace
  582. *
  583. * @param string $title
  584. * @param string $namespace segment namespace
  585. * @return e_admin_response
  586. */
  587. function prependTitle($title, $namespace = 'default')
  588. {
  589. if(empty($title))
  590. {
  591. return $this;
  592. }
  593. if(!isset($this->_title[$namespace]))
  594. {
  595. $this->_title[$namespace] = array();
  596. }
  597. $this->_title[$namespace] = array_merge(array($title), $this->_title[$namespace]);
  598. return $this;
  599. }
  600. /**
  601. * Get title segments from namespace
  602. *
  603. * @param string $namespace
  604. * @param boolean $reset
  605. * @param boolean|string $glue
  606. * @return unknown
  607. */
  608. function getTitle($namespace = 'default', $reset = false, $glue = ' ')
  609. {
  610. $content = array();
  611. if(isset($this->_title[$namespace]) && is_array($this->_title[$namespace]))
  612. {
  613. $content = $this->_title[$namespace];
  614. }
  615. if($reset)
  616. {
  617. unset($this->_title[$namespace]);
  618. }
  619. if(is_bool($glue) || empty($glue))
  620. {
  621. return ($glue ? $content : implode($this->_title_separator, $content));
  622. }
  623. $glue = deftrue('SEP',' - '); // Defined by admin theme. // admin-ui used only by bootstrap.
  624. return implode($glue, $content);
  625. // return $head. implode($glue, $content).$foot;
  626. }
  627. /**
  628. * Set render mode for a namespace
  629. *
  630. * @param string $render_mod
  631. * @param string $namespace
  632. * @return e_admin_response
  633. */
  634. function setRenderMod($render_mod, $namespace = 'default')
  635. {
  636. $this->_render_mod[$namespace] = $render_mod;
  637. return $this;
  638. }
  639. /**
  640. * Set render mode for namespace
  641. *
  642. * @param string $namespace
  643. * @return string
  644. */
  645. function getRenderMod($namespace = 'default')
  646. {
  647. return varset($this->_render_mod[$namespace], null);
  648. }
  649. /**
  650. * Add meta title, description and keywords segments
  651. *
  652. * @param string $meta property name
  653. * @param string $content meta content
  654. * @return e_admin_response
  655. */
  656. function addMetaData($meta, $content)
  657. {
  658. $tp = e107::getParser();
  659. $meta = '_' . $meta;
  660. if(isset($this->{$meta}) && !empty($content))
  661. {
  662. $this->{$meta}[] = strip_tags($content);
  663. }
  664. return $this;
  665. }
  666. /**
  667. * Add meta title segment
  668. *
  669. * @param string $title
  670. * @return e_admin_response
  671. */
  672. function addMetaTitle($title)
  673. {
  674. $this->addMetaData('e_PAGETITLE', $title);
  675. return $this;
  676. }
  677. /**
  678. * Add meta description segment
  679. *
  680. * @param string $description
  681. * @return e_admin_response
  682. */
  683. function addMetaDescription($description)
  684. {
  685. $this->addMetaData('META_DESCRIPTION', $description);
  686. return $this;
  687. }
  688. /**
  689. * Add meta keywords segment
  690. *
  691. * @param string $keyword
  692. * @return e_admin_response
  693. */
  694. function addMetaKeywords($keyword)
  695. {
  696. $this->addMetaData('META_KEYWORDS', $keyword);
  697. return $this;
  698. }
  699. /**
  700. * Send e107 meta-data
  701. *
  702. * @return e_admin_response
  703. */
  704. function sendMeta()
  705. {
  706. //HEADERF already included or meta content already sent
  707. if(e_AJAX_REQUEST || defined('HEADER_INIT') || defined('e_PAGETITLE'))
  708. return $this;
  709. if(!defined('e_PAGETITLE') && !empty($this->_e_PAGETITLE))
  710. {
  711. define('e_PAGETITLE', implode($this->_meta_title_separator, $this->_e_PAGETITLE));
  712. }
  713. if(!defined('META_DESCRIPTION') && !empty($this->_META_DESCRIPTION))
  714. {
  715. define('META_DESCRIPTION', implode(' ', $this->_META_DESCRIPTION));
  716. }
  717. if(!defined('META_KEYWORDS') && !empty($this->_META_KEYWORDS))
  718. {
  719. define('META_KEYWORDS', implode(', ', $this->_META_KEYWORDS));
  720. }
  721. return $this;
  722. }
  723. /**
  724. * Add content segment to the header namespace
  725. *
  726. * @param string $content
  727. * @return e_admin_response
  728. */
  729. function addHeaderContent($content)
  730. {
  731. $this->appendBody($content, 'header_content');
  732. return $this;
  733. }
  734. /**
  735. * Get page header namespace content segments
  736. *
  737. * @param boolean $reset
  738. * @param boolean $glue
  739. * @return string
  740. */
  741. function getHeaderContent($reset = true, $glue = "\n\n")
  742. {
  743. return $this->getBody('header_content', $reset, $glue);
  744. }
  745. /**
  746. * Switch to iframe mod
  747. * FIXME - implement e_IFRAME to frontend - header_default.php
  748. *
  749. * @return e_admin_response
  750. */
  751. function setIframeMod()
  752. {
  753. global $HEADER, $FOOTER, $CUSTOMHEADER, $CUSTOMFOOTER;
  754. $HEADER = $FOOTER = '';
  755. $CUSTOMHEADER = $CUSTOMFOOTER = array();
  756. //TODO generic $_GET to activate for any page of admin.
  757. // New
  758. if(!defined('e_IFRAME'))
  759. {
  760. define('e_IFRAME', true);
  761. }
  762. return $this;
  763. }
  764. /**
  765. * Send Response Output
  766. *
  767. * @param string $name segment
  768. * @param array $options valid keys are: messages|render|meta|return|raw|ajax
  769. * @return mixed
  770. */
  771. function send($name = 'default', $options = array())
  772. {
  773. if(is_string($options))
  774. {
  775. parse_str($options, $options);
  776. }
  777. // Merge with all available default options
  778. $options = array_merge(array(
  779. 'messages' => true,
  780. 'render' => true,
  781. 'meta' => false,
  782. 'return' => false,
  783. 'raw' => false,
  784. 'ajax' => false
  785. ), $options);
  786. $content = $this->getBody($name, true);
  787. $title = $this->getTitle($name, true);
  788. $return = $options['return'];
  789. if($options['ajax'] || e_AJAX_REQUEST)
  790. {
  791. $type = $options['ajax'] && is_string($options['ajax']) ? $options['ajax'] : '';
  792. $this->getJsHelper()->sendResponse($type);
  793. }
  794. if($options['messages'])
  795. {
  796. $content = e107::getMessage()->render().$content;
  797. }
  798. if($options['meta'])
  799. {
  800. $this->sendMeta();
  801. }
  802. // raw output expected - force return array
  803. if($options['raw'])
  804. {
  805. return array($title, $content, $this->getRenderMod($name));
  806. }
  807. //render disabled by the controller
  808. if(!$this->getRenderMod($name))
  809. {
  810. $options['render'] = false;
  811. }
  812. if($options['render'])
  813. {
  814. return e107::getRender()->tablerender($title, $content, $this->getRenderMod($name), $return);
  815. }
  816. if($return)
  817. {
  818. return $content;
  819. }
  820. print($content);
  821. return '';
  822. }
  823. /**
  824. * Get JS Helper instance
  825. *
  826. * @return e_jshelper
  827. */
  828. public function getJsHelper()
  829. {
  830. return e107::getSingleton('e_jshelper', true, 'admin_response');
  831. }
  832. }
  833. /**
  834. * TODO - request related code should be moved to core
  835. * request handler
  836. */
  837. class e_admin_dispatcher
  838. {
  839. /**
  840. * @var e_admin_request
  841. */
  842. protected $_request = null;
  843. /**
  844. * @var e_admin_response
  845. */
  846. protected $_response = null;
  847. /**
  848. * @var e_admin_controller
  849. */
  850. protected $_current_controller = null;
  851. /**
  852. * Required (set by child class).
  853. * Controller map array in format
  854. * 'MODE' => array('controller' =>'CONTROLLER_CLASS_NAME'[, 'path' => 'CONTROLLER SCRIPT PATH', 'ui' => extend of 'comments_admin_form_ui', 'uipath' => 'path/to/ui/']);
  855. *
  856. * @var array
  857. */
  858. protected $modes = array();
  859. /**
  860. * Optional - access restrictions per action
  861. * Access array in format (similar to adminMenu)
  862. * 'MODE/ACTION' => e_UC_* (userclass constant, or custom userclass ID if dynamically set)
  863. *
  864. * @var array
  865. */
  866. protected $access = array();
  867. /**
  868. * Optional - generic entry point access restriction (via getperms())
  869. * Value of this for plugins would be always 'P'.
  870. * More detailed access control is granted with $access and $modes[MODE]['perm'] or $modes[MODE]['userclass'] settings
  871. *
  872. * @var string
  873. */
  874. protected $perm;
  875. /**
  876. * @var string
  877. */
  878. protected $defaultMode = '';
  879. /**
  880. * @var string
  881. */
  882. protected $defaultAction = '';
  883. /**
  884. * Optional - map 'mode/action' pair to 'modeAlias/actionAlias'
  885. * @var string
  886. */
  887. protected $adminMenuAliases = array();
  888. /**
  889. * Optional (set by child class).
  890. * Required for admin menu render
  891. * Format: 'mode/action' => array('caption' => 'Link title'[, 'perm' => '0', 'url' => '{e_PLUGIN}plugname/admin_config.php'], ...);
  892. * Note that 'perm' and 'userclass' restrictions are inherited from the $modes, $access and $perm, so you don't have to set that vars if
  893. * you don't need any additional 'visual' control.
  894. * All valid key-value pair (see e107::getNav()->admin function) are accepted.
  895. * @var array
  896. */
  897. protected $adminMenu = array();
  898. /**
  899. * Optional (set by child class).
  900. * Page titles for pages not in adminMenu (e.g. main/edit)
  901. * Format array(mod/action => Page Title)
  902. * @var string
  903. */
  904. protected $pageTitles = array(
  905. 'main/edit' => LAN_MANAGE,
  906. );
  907. /**
  908. * Optional (set by child class).
  909. * @var string
  910. */
  911. protected $menuTitle = 'Menu';
  912. /**
  913. * @var string
  914. */
  915. protected $pluginTitle = '';
  916. /**
  917. * Constructor
  918. *
  919. * @param string|array|e_admin_request $request [optional]
  920. * @param e_admin_response $response
  921. */
  922. public function __construct($auto_observe = true, $request = null, $response = null)
  923. {
  924. // we let know some admin routines we are in UI mod - related with some legacy checks and fixes
  925. if(!defined('e_ADMIN_UI'))
  926. {
  927. define('e_ADMIN_UI', true);
  928. }
  929. require_once(e_ADMIN.'boot.php');
  930. if(null === $request || !is_object($request))
  931. {
  932. $request = new e_admin_request($request);
  933. }
  934. if(null === $response)
  935. {
  936. $response = new e_admin_response();
  937. }
  938. $this->setRequest($request)->setResponse($response)->init();
  939. if(!$this->defaultMode || !$this->defaultAction)
  940. {
  941. $this->setDefaults();
  942. }
  943. $request->setDefaultMode($this->defaultMode)->setDefaultAction($this->defaultAction);
  944. // register itself
  945. e107::setRegistry('admin/ui/dispatcher', $this);
  946. // permissions and restrictions
  947. $this->checkAccess();
  948. if($auto_observe)
  949. {
  950. $this->runObservers(true);
  951. }
  952. }
  953. /**
  954. * User defined constructor - called before _initController() method
  955. * @return e_admin_dispatcher
  956. */
  957. public function init()
  958. {
  959. }
  960. public function checkAccess()
  961. {
  962. $request = $this->getRequest();
  963. $currentMode = $request->getMode();
  964. // access based on mode setting - general controller access
  965. if(!$this->checkModeAccess($currentMode))
  966. {
  967. $request->setAction('e403');
  968. e107::getMessage()->addError('You don\'t have permissions to view this page.')
  969. ->addDebug('Mode access restriction triggered.');
  970. return false;
  971. }
  972. // access based on $access settings - access per action
  973. $currentAction = $request->getAction();
  974. $route = $currentMode.'/'.$currentAction;
  975. if(!$this->checkRouteAccess($route))
  976. {
  977. $request->setAction('e403');
  978. e107::getMessage()->addError('You don\'t have permissions to view this page.')
  979. ->addDebug('Route access restriction triggered.');
  980. return false;
  981. }
  982. return true;
  983. }
  984. public function checkModeAccess($mode)
  985. {
  986. // mode userclass (former check_class())
  987. if(isset($this->modes[$mode]['userclass']) && !e107::getUser()->checkClass($this->modes[$mode]['userclass'], false))
  988. {
  989. return false;
  990. }
  991. // mode admin permission (former getperms())
  992. if(isset($this->modes[$mode]['perm']) && !e107::getUser()->checkAdminPerms($this->modes[$mode]['perm']))
  993. {
  994. return false;
  995. }
  996. // generic dispatcher admin permission (former getperms())
  997. if(null !== $this->perm && !e107::getUser()->checkAdminPerms($this->perm))
  998. {
  999. return false;
  1000. }
  1001. return true;
  1002. }
  1003. public function checkRouteAccess($route)
  1004. {
  1005. if(isset($this->access[$route]) && !e107::getUser()->checkClass($this->access[$route], false))
  1006. {
  1007. return false;
  1008. }
  1009. return true;
  1010. }
  1011. /**
  1012. * Retrieve missing default action/mode
  1013. * @return e_admin_dispatcher
  1014. */
  1015. public function setDefaults()
  1016. {
  1017. // try Admin menu first
  1018. if($this->adminMenu)
  1019. {
  1020. reset($this->adminMenu);
  1021. list($mode, $action) = explode('/', key($this->adminMenu), 3);
  1022. }
  1023. else
  1024. {
  1025. reset($this->modes);
  1026. $mode = key($this->modes);
  1027. $action = $this->modes[$mode]['index'];
  1028. }
  1029. if(!$this->defaultMode) $this->defaultMode = $mode;
  1030. if(!$this->defaultAction) $this->defaultAction = $action;
  1031. return $this;
  1032. }
  1033. /**
  1034. * Get admin menu array
  1035. * @return array
  1036. */
  1037. public function getMenuData()
  1038. {
  1039. return $this->adminMenu;
  1040. }
  1041. /**
  1042. * Get admin menu array
  1043. * @return array
  1044. */
  1045. public function getPageTitles()
  1046. {
  1047. return $this->pageTitles;
  1048. }
  1049. /**
  1050. * Get admin menu array
  1051. * @return array
  1052. */
  1053. public function getMenuAliases()
  1054. {
  1055. return $this->adminMenuAliases;
  1056. }
  1057. /**
  1058. * Get request object
  1059. * @return e_admin_request
  1060. */
  1061. public function getRequest()
  1062. {
  1063. return $this->_request;
  1064. }
  1065. /**
  1066. * Set request object
  1067. * @param e_admin_request $request
  1068. * @return e_admin_dispatcher
  1069. */
  1070. public function setRequest($request)
  1071. {
  1072. $this->_request = $request;
  1073. return $this;
  1074. }
  1075. /**
  1076. * Get response object
  1077. * @return e_admin_response
  1078. */
  1079. public function getResponse()
  1080. {
  1081. return $this->_response;
  1082. }
  1083. /**
  1084. * Set response object
  1085. * @param e_admin_response $response
  1086. * @return e_admin_dispatcher
  1087. */
  1088. public function setResponse($response)
  1089. {
  1090. $this->_response = $response;
  1091. return $this;
  1092. }
  1093. /**
  1094. * Dispatch & render all
  1095. *
  1096. * @param boolean $run_header see runObservers()
  1097. * @param boolean $return see runPage()
  1098. * @return string|array current admin page body
  1099. */
  1100. public function run($run_header = true, $return = 'render')
  1101. {
  1102. return $this->runObservers()->runPage($return);
  1103. }
  1104. /**
  1105. * Run observers/headers only, should be called before header.php call
  1106. *
  1107. * @return e_admin_dispatcher
  1108. */
  1109. public function runObservers($run_header = true)
  1110. {
  1111. //search for $actionName.'Observer' method. Additional $actionName.$triggerName.'Trigger' methods will be called as well
  1112. $this->getController()->dispatchObserver();
  1113. //search for $actionName.'Header' method, js manager should be used inside for sending JS to the page,
  1114. // meta information should be created there as well
  1115. if($run_header)
  1116. {
  1117. $this->getController()->dispatchHeader();
  1118. }
  1119. return $this;
  1120. }
  1121. /**
  1122. * Run page action.
  1123. * If return type is array, it should contain allowed response options (see e_admin_response::send())
  1124. * Available return type string values:
  1125. * - render_return: return rendered content ( see e107::getRender()->tablerender()), add system messages, send meta information
  1126. * - render: outputs rendered content ( see e107::getRender()->tablerender()), add system messages
  1127. * - response: return response object
  1128. * - raw: return array(title, content, render mode)
  1129. * - ajax: force ajax output (and exit)
  1130. *
  1131. * @param string|array $return_type expected string values: render|render_out|response|raw|ajax[_text|_json|_xml]
  1132. * @return mixed
  1133. */
  1134. public function runPage($return_type = 'render')
  1135. {
  1136. $response = $this->getController()->dispatchPage();
  1137. if(is_array($return_type))
  1138. {
  1139. return $response->send('default', $return_type);
  1140. }
  1141. switch($return_type)
  1142. {
  1143. case 'render_return':
  1144. $options = array(
  1145. 'messages' => true,
  1146. 'render' => true,
  1147. 'meta' => true,
  1148. 'return' => true,
  1149. 'raw' => false
  1150. );
  1151. break;
  1152. case 'raw':
  1153. $options = array(
  1154. 'messages' => false,
  1155. 'render' => false,
  1156. 'meta' => false,
  1157. 'return' => true,
  1158. 'raw' => true
  1159. );
  1160. break;
  1161. case 'ajax':
  1162. case 'ajax_text':
  1163. case 'ajax_xml';
  1164. case 'ajax_json';
  1165. $options = array(
  1166. 'messages' => false,
  1167. 'render' => false,
  1168. 'meta' => false,
  1169. 'return' => false,
  1170. 'raw' => false,
  1171. 'ajax' => str_replace(array('ajax_', 'ajax'), array('', 'text'), $return_type)
  1172. );
  1173. break;
  1174. case 'response':
  1175. return $response;
  1176. break;
  1177. case 'render':
  1178. default:
  1179. $options = array(
  1180. 'messages' => true,
  1181. 'render' => true,
  1182. 'meta' => false,
  1183. 'return' => false,
  1184. 'raw' => false
  1185. );
  1186. break;
  1187. }
  1188. return $response->send('default', $options);
  1189. }
  1190. /**
  1191. * Proxy method
  1192. *
  1193. * @return string
  1194. */
  1195. public function getHeader()
  1196. {
  1197. return $this->getController()->getHeader();
  1198. }
  1199. /**
  1200. * Get current controller object
  1201. * @return e_admin_controller
  1202. */
  1203. public function getController()
  1204. {
  1205. if(null === $this->_current_controller)
  1206. {
  1207. $this->_initController();
  1208. }
  1209. return $this->_current_controller;
  1210. }
  1211. /**
  1212. * Try to init Controller from request using current controller map
  1213. *
  1214. * @return e_admin_dispatcher
  1215. */
  1216. protected function _initController()
  1217. {
  1218. $request = $this->getRequest();
  1219. $response = $this->getResponse();
  1220. if(isset($this->modes[$request->getModeName()]) && isset($this->modes[$request->getModeName()]['controller']))
  1221. {
  1222. $class_name = $this->modes[$request->getModeName()]['controller'];
  1223. $class_path = vartrue($this->modes[$request->getModeName()]['path']);
  1224. if($class_path)
  1225. {
  1226. require_once(e107::getParser()->replaceConstants($class_path));
  1227. }
  1228. if($class_name && class_exists($class_name))//NOTE: autoload in the play
  1229. {
  1230. $this->_current_controller = new $class_name($request, $response);
  1231. //give access to current request object, user defined init
  1232. $this->_current_controller->setRequest($this->getRequest())->init();
  1233. }
  1234. // Known controller (found in e_admin_dispatcher::$modes), class not found exception
  1235. else
  1236. {
  1237. // TODO - admin log
  1238. // get default controller
  1239. $this->_current_controller = $this->getDefaultController();
  1240. // add messages
  1241. e107::getMessage()->add('Can\'t find class <strong>&quot;'.($class_name ? $class_name : 'n/a').'&quot;</strong> for controller <strong>&quot;'.ucfirst($request->getModeName()).'&quot;</strong>', E_MESSAGE_ERROR)
  1242. ->add('Requested: '.e_SELF.'?'.$request->buildQueryString(), E_MESSAGE_DEBUG);
  1243. //
  1244. $request->setMode($this->getDefaultControllerName())->setAction('e404');
  1245. $this->_current_controller->setRequest($request)->init();
  1246. }
  1247. if(vartrue($this->modes[$request->getModeName()]['ui']))
  1248. {
  1249. $class_name = $this->modes[$request->getModeName()]['ui'];
  1250. $class_path = vartrue($this->modes[$request->getModeName()]['uipath']);
  1251. if($class_path)
  1252. {
  1253. require_once(e107::getParser()->replaceConstants($class_path));
  1254. }
  1255. if(class_exists($class_name))//NOTE: autoload in the play
  1256. {
  1257. $this->_current_controller->setParam('ui', new $class_name($this->_current_controller));
  1258. }
  1259. }
  1260. $this->_current_controller->setParam('modes', $this->modes);
  1261. }
  1262. // Not known controller (not found in e_admin_dispatcher::$modes) exception
  1263. else
  1264. {
  1265. // TODO - admin log
  1266. $this->_current_controller = $this->getDefaultController();
  1267. // add messages
  1268. e107::getMessage()->add('Can\'t find class for controller <strong>&quot;'.ucfirst($request->getModeName()).'&quot;</strong>', E_MESSAGE_ERROR)
  1269. ->add('Requested: '.e_SELF.'?'.$request->buildQueryString(), E_MESSAGE_DEBUG);
  1270. // go to not found page
  1271. $request->setMode($this->getDefaultControllerName())->setAction('e404');
  1272. $this->_current_controller->setRequest($request)->init();
  1273. }
  1274. return $this;
  1275. }
  1276. /**
  1277. * Default controller object - needed if controller not found
  1278. * @return e_admin_controller
  1279. */
  1280. public function getDefaultController()
  1281. {
  1282. $class_name = $this->getDefaultControllerName();
  1283. return new $class_name($this->getRequest(), $this->getResponse());
  1284. }
  1285. /**
  1286. * Default controller name - needed if controller not found
  1287. * @return string name of controller
  1288. */
  1289. public function getDefaultControllerName()
  1290. {
  1291. return 'e_admin_controller';
  1292. }
  1293. /**
  1294. * Generic Admin Menu Generator
  1295. * @return string
  1296. */
  1297. function renderMenu()
  1298. {
  1299. $tp = e107::getParser();
  1300. $var = array();
  1301. $selected = false;
  1302. foreach($this->adminMenu as $key => $val)
  1303. {
  1304. $tmp = explode('/', trim($key, '/'), 3);
  1305. // sync with mode/route access
  1306. if(!$this->checkModeAccess($tmp[0]) || !$this->checkRouteAccess($tmp[0].'/'.$tmp[1]))
  1307. {
  1308. continue;
  1309. }
  1310. // custom 'selected' check
  1311. if(isset($val['selected']) && $val['selected']) $selected = $val['selected'] === true ? $key : $val['selected'];
  1312. foreach ($val as $k=>$v)
  1313. {
  1314. switch($k)
  1315. {
  1316. case 'caption':
  1317. $k2 = 'text';
  1318. $v = defset($v, $v);
  1319. break;
  1320. case 'url':
  1321. $k2 = 'link';
  1322. $v = $tp->replaceConstants($v, 'abs').'?mode='.$tmp[0].'&amp;action='.$tmp[1];
  1323. break;
  1324. case 'uri':
  1325. $k2 = 'link';
  1326. $v = $tp->replaceConstants($v, 'abs');
  1327. break;
  1328. default:
  1329. $k2 = $k;
  1330. break;
  1331. }
  1332. // Access check done above
  1333. // if($val['perm']!= null) // check perms
  1334. // {
  1335. // if(getperms($val['perm']))
  1336. // {
  1337. // $var[$key][$k2] = $v;
  1338. // }
  1339. // }
  1340. // else
  1341. {
  1342. $var[$key][$k2] = $v;
  1343. }
  1344. }
  1345. // TODO slide down menu options?
  1346. if(!vartrue($var[$key]['link']))
  1347. {
  1348. $var[$key]['link'] = e_SELF.'?mode='.$tmp[0].'&amp;action='.$tmp[1]; // FIXME - URL based on $modes, remove url key
  1349. }
  1350. if(varset($val['tab']))
  1351. {
  1352. $var[$key]['link'] .= "&amp;tab=".$val['tab'];
  1353. }
  1354. /*$var[$key]['text'] = $val['caption'];
  1355. $var[$key]['link'] = (vartrue($val['url']) ? $tp->replaceConstants($val['url'], 'abs') : e_SELF).'?mode='.$tmp[0].'&action='.$tmp[1];
  1356. $var[$key]['perm'] = $val['perm']; */
  1357. }
  1358. if(empty($var)) return '';
  1359. $request = $this->getRequest();
  1360. if(!$selected) $selected = $request->getMode().'/'.$request->getAction();
  1361. $selected = vartrue($this->adminMenuAliases[$selected], $selected);
  1362. return e107::getNav()->admin($this->menuTitle, $selected, $var);
  1363. }
  1364. /**
  1365. * Render Help Text in <ul> format. XXX TODO
  1366. */
  1367. function renderHelp()
  1368. {
  1369. }
  1370. /**
  1371. * Check for table issues and warn the user. XXX TODO
  1372. * ie. user is using French interface but no french tables found for the current DB tables.
  1373. */
  1374. function renderWarnings()
  1375. {
  1376. }
  1377. }
  1378. class e_admin_controller
  1379. {
  1380. /**
  1381. * @var e_admin_request
  1382. */
  1383. protected $_request;
  1384. /**
  1385. * @var e_admin_response
  1386. */
  1387. protected $_response;
  1388. /**
  1389. * @var array User defined parameters
  1390. */
  1391. protected $_params = array();
  1392. /**
  1393. * @var string default action name
  1394. */
  1395. protected $_default_action = 'index';
  1396. /**
  1397. * List (numerical array) of only allowed for this controller actions
  1398. * Useful to grant access for certain pre-defined actions only
  1399. * XXX - we may move this in dispatcher (or even having it also there), still searching the most 'friendly' way
  1400. * @var array
  1401. */
  1402. protected $allow = array();
  1403. /**
  1404. * List (numerical array) of only disallowed for this controller actions
  1405. * Useful to restrict access for certain pre-defined actions only
  1406. * XXX - we may move this in dispatcher (or even having it also there), still searching the most 'friendly' way
  1407. * @var array
  1408. */
  1409. protected $disallow = array();
  1410. /**
  1411. * Constructor
  1412. * @param e_admin_request $request [optional]
  1413. */
  1414. public function __construct($request, $response, $params = array())
  1415. {
  1416. $this->_params = array_merge(array('enable_triggers' => false), $params);
  1417. $this->setRequest($request)
  1418. ->setResponse($response)
  1419. ->setParams($params);
  1420. $this->checkAccess();
  1421. }
  1422. /**
  1423. * Check against allowed/disallowed actions
  1424. * FIXME check plugin admin access (check_class(P)), confirm e-token is verified
  1425. */
  1426. public function checkAccess()
  1427. {
  1428. $request = $this->getRequest();
  1429. $currentAction = $request->getAction();
  1430. // access based on mode setting - general controller access
  1431. if(!empty($this->disallow) && in_array($currentAction, $this->disallow))
  1432. {
  1433. $request->setAction('e403');
  1434. e107::getMessage()->addError('You don\'t have permissions to view this page.')
  1435. ->addDebug('Controller action disallowed restriction triggered.');
  1436. return false;
  1437. }
  1438. // access based on $access settings - access per action
  1439. if(!empty($this->allow) && !in_array($currentAction, $this->allow))
  1440. {
  1441. $request->setAction('e403');
  1442. e107::getMessage()->addError('You don\'t have permissions to view this page.')
  1443. ->addDebug('Controller action not in allowed list restriction triggered.');
  1444. return false;
  1445. }
  1446. return true;
  1447. }
  1448. /**
  1449. * User defined init
  1450. * Called before dispatch routine
  1451. */
  1452. public function init()
  1453. {
  1454. }
  1455. /**
  1456. * Get controller parameter
  1457. * Currently used core parameters:
  1458. * - enable_triggers: don't use it direct, see {@link setTriggersEnabled()}
  1459. * - modes - see dispatcher::$modes
  1460. * - ajax_response - text|xml|json - default is 'text'; this should be set by the action method
  1461. * - TODO - more parameters/add missing to this list
  1462. *
  1463. * @param string $key [optional] if null - get whole array
  1464. * @param mixed $default [optional]
  1465. * @return mixed
  1466. */
  1467. public function getParam($key = null, $default = null)
  1468. {
  1469. if(null === $key)
  1470. {
  1471. return $this->_params;
  1472. }
  1473. return (isset($this->_params[$key]) ? $this->_params[$key] : $default);
  1474. }
  1475. /**
  1476. * Set parameter
  1477. * @param string $key
  1478. * @param mixed $value
  1479. * @return e_admin_controller
  1480. */
  1481. public function setParam($key, $value)
  1482. {
  1483. if(null === $value)
  1484. {
  1485. unset($this->_params[$key]);
  1486. return $this;
  1487. }
  1488. $this->_params[$key] = $value;
  1489. return $this;
  1490. }
  1491. /**
  1492. * Merge passed parameter array with current parameters
  1493. * @param array $params
  1494. * @return e_admin_controller
  1495. */
  1496. public function setParams($params)
  1497. {
  1498. $this->_params = array_merge($this->_params, $params);
  1499. return $this;
  1500. }
  1501. /**
  1502. * Reset parameter array
  1503. * @param array $params
  1504. * @return e_admin_controller
  1505. */
  1506. public function resetParams($params)
  1507. {
  1508. $this->_params = $params;
  1509. return $this;
  1510. }
  1511. /**
  1512. * Get current request object
  1513. * @return e_admin_request
  1514. */
  1515. public function getRequest()
  1516. {
  1517. return $this->_request;
  1518. }
  1519. /**
  1520. * Set current request object
  1521. * @param e_admin_request $request
  1522. * @return e_admin_controller
  1523. */
  1524. public function setRequest($request)
  1525. {
  1526. $this->_request = $request;
  1527. return $this;
  1528. }
  1529. /**
  1530. * Get current response object
  1531. * @return e_admin_response
  1532. */
  1533. public function getResponse()
  1534. {
  1535. return $this->_response;
  1536. }
  1537. /**
  1538. * Set current response object
  1539. * @param e_admin_response $response
  1540. * @return e_admin_controller
  1541. */
  1542. public function setResponse($response)
  1543. {
  1544. $this->_response = $response;
  1545. return $this;
  1546. }
  1547. /**
  1548. * Get current dispatcher object
  1549. * @return e_admin_dispatcher
  1550. */
  1551. public function getDispatcher()
  1552. {
  1553. return e107::getRegistry('admin/ui/dispatcher');
  1554. }
  1555. /**
  1556. * Request proxy method
  1557. * @param string $key [optional]
  1558. * @param mixed $default [optional]
  1559. * @return mixed
  1560. */
  1561. public function getQuery($key = null, $default = null)
  1562. {
  1563. return $this->getRequest()->getQuery($key, $default);
  1564. }
  1565. /**
  1566. * Request proxy method
  1567. * @param string|array $key
  1568. * @param mixed $value [optional]
  1569. * @return e_admin_controller
  1570. */
  1571. public function setQuery($key, $value = null)
  1572. {
  1573. $this->getRequest()->setQuery($key, $value);
  1574. return $this;
  1575. }
  1576. /**
  1577. * Request proxy method
  1578. * @param string $key [optional]
  1579. * @param mixed $default [optional]
  1580. * @return mixed
  1581. */
  1582. public function getPosted($key = null, $default = null)
  1583. {
  1584. return $this->getRequest()->getPosted($key, $default);
  1585. }
  1586. /**
  1587. * Request proxy method
  1588. * @param string $key
  1589. * @param mixed $value [optional]
  1590. * @return e_admin_controller
  1591. */
  1592. public function setPosted($key, $value = null)
  1593. {
  1594. $this->getRequest()->setPosted($key, $value);
  1595. return $this;
  1596. }
  1597. /**
  1598. * Add page title, response proxy method
  1599. *
  1600. * @param string $title if boolean true - current menu caption will be used
  1601. * @param boolean $meta add to meta as well
  1602. * @return e_admin_controller
  1603. */
  1604. public function addTitle($title = true, $meta = true)
  1605. {
  1606. if(true === $title)
  1607. {
  1608. $_dispatcher = $this->getDispatcher();
  1609. $data = $_dispatcher->getPageTitles();
  1610. $search = $this->getMode().'/'.$this->getAction();
  1611. if(isset($data[$search])) $res['caption'] = $data[$search];
  1612. else
  1613. {
  1614. $data = $_dispatcher->getMenuData();
  1615. if(isset($data[$search])) $res = $data[$search];
  1616. else return $this;
  1617. }
  1618. $title = $res['caption'];
  1619. }
  1620. // print_a($title);
  1621. $this->getResponse()->appendTitle($title);
  1622. if($meta) $this->addMetaTitle($title);
  1623. return $this;
  1624. }
  1625. /**
  1626. * Add page meta title, response proxy method.
  1627. * Should be called before header.php
  1628. *
  1629. * @param string $title
  1630. * @return e_admin_controller
  1631. */
  1632. public function addMetaTitle($title)
  1633. {
  1634. $this->getResponse()->addMetaTitle($title);
  1635. return $this;
  1636. }
  1637. /**
  1638. * Add header content, response proxy method
  1639. * Should be called before header.php
  1640. *
  1641. * @param string $content
  1642. * @return e_admin_controller
  1643. */
  1644. public function addHeader($content)
  1645. {
  1646. $this->getResponse()->addHeaderContent(vartrue($content));
  1647. return $this;
  1648. }
  1649. /**
  1650. * Get header content, response proxy method
  1651. *
  1652. * @return string
  1653. */
  1654. public function getHeader()
  1655. {
  1656. return $this->getResponse()->getHeaderContent();
  1657. }
  1658. /**
  1659. * Get current mode, response proxy method
  1660. * @return string
  1661. */
  1662. public function getMode()
  1663. {
  1664. return $this->getRequest()->getMode();
  1665. }
  1666. /**
  1667. * Get current actin, response proxy method
  1668. * @return string
  1669. */
  1670. public function getAction()
  1671. {
  1672. return $this->getRequest()->getAction();
  1673. }
  1674. /**
  1675. * Get current ID, response proxy method
  1676. * @return string
  1677. */
  1678. public function getId()
  1679. {
  1680. return $this->getRequest()->getId();
  1681. }
  1682. /**
  1683. * Get response owned JS Helper instance, response proxy method
  1684. *
  1685. * @return e_jshelper
  1686. */
  1687. public function getJsHelper()
  1688. {
  1689. return $this->getResponse()->getJsHelper();
  1690. }
  1691. protected function _preDispatch($action = '')
  1692. {
  1693. if(!$action) $action = $this->getRequest()->getActionName();
  1694. $method = $this->toMethodName($action, 'page');
  1695. if(!method_exists($this, $method))
  1696. {
  1697. $this->getRequest()->setAction($this->getDefaultAction());
  1698. }
  1699. // switch to 404 if needed
  1700. $method = $this->toMethodName($this->getRequest()->getActionName(), 'page');
  1701. if(!method_exists($this, $method))
  1702. {
  1703. $this->getRequest()->setAction('e404');
  1704. $message = e107::getParser()->lanVars(LAN_UI_404_METHOD_ERROR, $method, true);
  1705. e107::getMessage()->add($message, E_MESSAGE_ERROR);
  1706. }
  1707. }
  1708. /**
  1709. * Dispatch observer, check for triggers
  1710. *
  1711. * @param string $action [optional]
  1712. * @return e_admin_controller
  1713. */
  1714. public function dispatchObserver($action = null)
  1715. {
  1716. $request = $this->getRequest();
  1717. if(null === $request)
  1718. {
  1719. $request = new e_admin_request();
  1720. $this->setRequest($request);
  1721. }
  1722. $this->_preDispatch($action);
  1723. if(null === $action)
  1724. {
  1725. $action = $request->getActionName();
  1726. }
  1727. // check for observer
  1728. $actionObserverName = $this->toMethodName($action, 'observer', e_AJAX_REQUEST);
  1729. if(method_exists($this, $actionObserverName))
  1730. {
  1731. $this->$actionObserverName();
  1732. }
  1733. // check for triggers, not available in Ajax mode
  1734. if(!e_AJAX_REQUEST && $this->triggersEnabled())
  1735. {
  1736. $posted = $request->getPosted();
  1737. foreach ($posted as $key => $value)
  1738. {
  1739. if(strpos($key, 'etrigger_') === 0)
  1740. {
  1741. $actionTriggerName = $this->toMethodName($action.$request->camelize(substr($key, 9)), 'trigger', false);
  1742. if(method_exists($this, $actionTriggerName))
  1743. {
  1744. $this->$actionTriggerName($value);
  1745. }
  1746. //Check if triggers are still enabled
  1747. if(!$this->triggersEnabled())
  1748. {
  1749. break;
  1750. }
  1751. }
  1752. }
  1753. }
  1754. return $this;
  1755. }
  1756. /**
  1757. * Dispatch header, not allowed in Ajax mode
  1758. * @param string $action [optional]
  1759. * @return e_admin_controller
  1760. */
  1761. public function dispatchHeader($action = null)
  1762. {
  1763. // not available in Ajax mode
  1764. if(e_AJAX_REQUEST)
  1765. {
  1766. return $this;
  1767. }
  1768. $request = $this->getRequest();
  1769. if(null === $request)
  1770. {
  1771. $request = new e_admin_request();
  1772. $this->setRequest($request);
  1773. }
  1774. $this->_preDispatch($action);
  1775. if(null === $action)
  1776. {
  1777. $action = $request->getActionName();
  1778. }
  1779. // check for observer
  1780. $actionHeaderName = $this->toMethodName($action, 'header', false);
  1781. if(method_exists($this, $actionHeaderName))
  1782. {
  1783. $this->$actionHeaderName();
  1784. }
  1785. //send meta data
  1786. $this->getResponse()->sendMeta();
  1787. return $this;
  1788. }
  1789. /**
  1790. * Dispatch controller action
  1791. *
  1792. * @param string $action [optional]
  1793. * @return e_admin_response
  1794. */
  1795. public function dispatchPage($action = null)
  1796. {
  1797. $request = $this->getRequest();
  1798. if(null === $request)
  1799. {
  1800. $request = new e_admin_request();
  1801. $this->setRequest($request);
  1802. }
  1803. $response = $this->getResponse();
  1804. $this->_preDispatch($action);
  1805. if(null === $action)
  1806. {
  1807. $action = $request->getActionName();
  1808. }
  1809. // check for observer
  1810. $actionName = $this->toMethodName($action, 'page');
  1811. $ret = '';
  1812. if(!method_exists($this, $actionName)) // pre dispatch already switched to default action/not found page if needed
  1813. {
  1814. e107::getMessage()->add('Action '.$actionName.' no found!', E_MESSAGE_ERROR);
  1815. return $response;
  1816. }
  1817. ob_start(); //catch any output
  1818. $ret = $this->{$actionName}();
  1819. //Ajax XML/JSON communication
  1820. if(e_AJAX_REQUEST && is_array($ret))
  1821. {
  1822. $response_type = $this->getParam('ajax_response', 'xml');
  1823. ob_clean();
  1824. $js_helper = $response->getJsHelper();
  1825. foreach ($ret as $act => $data)
  1826. {
  1827. $js_helper->addResponse($data, $act);
  1828. }
  1829. $js_helper->sendResponse($response_type);
  1830. }
  1831. $ret .= ob_get_clean();
  1832. // Ajax text response
  1833. if(e_AJAX_REQUEST)
  1834. {
  1835. $response_type = 'text';
  1836. $response->getJsHelper()->addResponse($ret)->sendResponse($response_type);
  1837. }
  1838. else
  1839. {
  1840. $response->appendBody($ret);
  1841. }
  1842. return $response;
  1843. }
  1844. public function E404Observer()
  1845. {
  1846. $this->getResponse()->setTitle(LAN_UI_404_TITLE_ERROR);
  1847. }
  1848. public function E404Page()
  1849. {
  1850. return '<div class="center">'.LAN_UI_404_BODY_ERROR.'</div>'; // TODO - lan
  1851. }
  1852. public function E404AjaxPage()
  1853. {
  1854. exit;
  1855. }
  1856. public function E403Observer()
  1857. {
  1858. $this->getResponse()->setTitle(LAN_UI_403_TITLE_ERROR);
  1859. }
  1860. public function E403Page()
  1861. {
  1862. return '<div class="center">'.LAN_UI_403_BODY_ERROR.'</div>'; // TODO - lan
  1863. }
  1864. public function E403AjaxPage()
  1865. {
  1866. exit;
  1867. }
  1868. /**
  1869. * Generic redirect handler, it handles almost everything we would need.
  1870. * Additionally, it moves currently registered system messages to SESSION message stack
  1871. * In almost every case {@link redirectAction()} and {@link redirectMode()} are better solution
  1872. *
  1873. * @param string $action defaults to current action
  1874. * @param string $mode defaults to current mode
  1875. * @param string|array $exclude_query comma delimited variable names to be excluded from current query OR TRUE to exclude everything
  1876. * @param string|array $merge_query query string (&amp; delimiter) or associative array to be merged with current query
  1877. * @param string $path default to e_SELF
  1878. * @return void
  1879. */
  1880. public function redirect($action = null, $mode = null, $exclude_query = '', $merge_query = array(), $path = null)
  1881. {
  1882. $request = $this->getRequest();
  1883. if($mode) $request->setMode($mode);
  1884. if($action) $request->setAction($action);
  1885. if(!$path) $path = e_SELF;
  1886. //prevent cache
  1887. header('Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
  1888. // header('Pragma: no-cache');
  1889. $url = $path.'?'.$request->buildQueryString($merge_query, false, $exclude_query);
  1890. // Transfer all messages to session
  1891. e107::getMessage()->moveToSession();
  1892. // write session data
  1893. session_write_close();
  1894. // do redirect
  1895. header('Location: '.$url);
  1896. exit;
  1897. }
  1898. /**
  1899. * Convenient redirect() proxy method, make life easier when redirecting between actions
  1900. * in same mode.
  1901. *
  1902. * @param string $action [optional]
  1903. * @param string|array $exclude_query [optional]
  1904. * @param string|array $merge_query [optional]
  1905. * @return none
  1906. */
  1907. public function redirectAction($action = null, $exclude_query = '', $merge_query = array())
  1908. {
  1909. $this->redirect($action, null, $exclude_query, $merge_query);
  1910. }
  1911. /**
  1912. * Convenient redirect to another mode (doesn't use current Query state)
  1913. * If path is empty, it'll be auto-detected from modes (dispatcher) array
  1914. *
  1915. * @param string $mode
  1916. * @param string $action
  1917. * @param string|array $query [optional]
  1918. * @param string $path
  1919. * @return void
  1920. */
  1921. public function redirectMode($mode, $action, $query = array(), $path = null)
  1922. {
  1923. if(!$path && $this->getParam('modes'))
  1924. {
  1925. $modes = $this->getParam('modes');
  1926. if(vartue($modes[$mode]) && vartrue($modes[$mode]['url']))
  1927. {
  1928. $path = e107::getParser()->replaceConstants($modes[$mode]['url'], 'abs');
  1929. }
  1930. }
  1931. $this->redirect($action, $mode, true, $query, $path);
  1932. }
  1933. /**
  1934. * Convert action name to method name
  1935. *
  1936. * @param string $action_name formatted (e.g. request method getActionName()) action name
  1937. * @param string $type page|observer|header|trigger
  1938. * @param boolean $ajax force with true/false, if null will be auto-resolved
  1939. * @return string
  1940. */
  1941. public function toMethodName($action_name, $type= 'page', $ajax = null)
  1942. {
  1943. if(null === $ajax) $ajax = e_AJAX_REQUEST; //auto-resolving
  1944. return $action_name.($ajax ? 'Ajax' : '').ucfirst(strtolower($type));
  1945. }
  1946. /**
  1947. * Check if there is a trigger available in the posted data
  1948. * @param array $exclude
  1949. * @return boolean
  1950. */
  1951. public function hasTrigger($exclude = array())
  1952. {
  1953. $posted = array_keys($this->getPosted());
  1954. foreach ($posted as $key)
  1955. {
  1956. if(!in_array($key, $exclude) && strpos($key, 'etrigger_') === 0)
  1957. {
  1958. return true;
  1959. }
  1960. }
  1961. return false;
  1962. }
  1963. /**
  1964. * Get default action
  1965. * @return string action
  1966. */
  1967. public function getDefaultAction()
  1968. {
  1969. return $this->_default_action;
  1970. }
  1971. /**
  1972. * Set default action
  1973. * @param string $action_name
  1974. * @return e_admin_controller
  1975. */
  1976. public function setDefaultAction($action_name)
  1977. {
  1978. $this->_default_action = $action_name;
  1979. return $this;
  1980. }
  1981. /**
  1982. * @return boolean
  1983. */
  1984. public function triggersEnabled()
  1985. {
  1986. return $this->getParam('enable_triggers');
  1987. }
  1988. /**
  1989. * @param boolean $flag
  1990. * @return e_admin_controller
  1991. */
  1992. public function setTriggersEnabled($flag)
  1993. {
  1994. $this->setParam('enable_triggers', $flag);
  1995. return $this;
  1996. }
  1997. }
  1998. //FIXME - move everything from e_admin_ui except model auto-create related code
  1999. class e_admin_controller_ui extends e_admin_controller
  2000. {
  2001. /**
  2002. * @var array UI field data
  2003. */
  2004. protected $fields = array();
  2005. /**
  2006. * @var array default fields activated on List view
  2007. */
  2008. protected $fieldpref = array();
  2009. /**
  2010. * @var array Plugin Preference description array
  2011. */
  2012. protected $prefs = array();
  2013. /**
  2014. * Data required for _modifyListQry() to automate
  2015. * db query building
  2016. * @var array
  2017. */
  2018. protected $tableJoin = array();
  2019. /**
  2020. * Array of table names and their a…

Large files files are truncated, but you can click here to view the full file