/e107_handlers/admin_ui.php
PHP | 5872 lines | 3529 code | 715 blank | 1628 comment | 486 complexity | 34ed6a3c5068ad414d571024b6ab9174 MD5 | raw file
Possible License(s): GPL-2.0
- <?php
- /*
- * e107 website system
- *
- * Copyright (C) 2008-2012 e107 Inc (e107.org)
- * Released under the terms and conditions of the
- * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
- *
- * Administration User Interface logic
- *
- * $URL$
- * $Id$
- */
- /**
- * @package e107
- * @subpackage e107_handlers
- * @version $Id$
- *
- * Administration User Interface logic
- */
- /**
- * @todo core request handler (non-admin), core response
- */
- if (!defined('e107_INIT')){ exit; }
-
-
- class e_admin_request
- {
- /**
- * Current GET request array
- * @var array
- */
- protected $_request_qry;
- /**
- * Current POST array
- * @var array
- */
- protected $_posted_qry;
- /**
- * Current Mode
- * @var string
- */
- protected $_mode = '';
- /**
- * Default Mode
- * @var string
- */
- protected $_default_mode = 'main';
- /**
- * Key name for mode search
- * @var string
- */
- protected $_mode_key = 'mode';
- /**
- * Current action
- * @var string
- */
- protected $_action = '';
- /**
- * Default Action
- * @var string
- */
- protected $_default_action = 'index';
- /**
- * Key name for action search
- * @var string
- */
- protected $_action_key = 'action';
- /**
- * Current ID
- * @var integer
- */
- protected $_id = 0;
- /**
- * Key name for ID search
- * @var string
- */
- protected $_id_key = 'id';
- /**
- * Constructor
- *
- * @param string|array $qry [optional]
- * @return none
- */
- public function __construct($request_string = null, $parse = true)
- {
- if(null === $request_string)
- {
- $request_string = str_replace('&', '&', e_QUERY);
- }
- if($parse)
- {
- $this->parseRequest($request_string);
- }
- }
- /**
- * Parse request data
- * @param string|array $request_data
- * @return e_admin_request
- */
- protected function parseRequest($request_data)
- {
- if(is_string($request_data))
- {
- parse_str($request_data, $request_data);
- }
- $this->_request_qry = (array) $request_data;
- // Set current mode
- if(isset($this->_request_qry[$this->_mode_key]))
- {
- $this->_mode = preg_replace('/[^\w]/', '', $this->_request_qry[$this->_mode_key]);
- }
- // Set current action
- if(isset($this->_request_qry[$this->_action_key]))
- {
- $this->_action = preg_replace('/[^\w]/', '', $this->_request_qry[$this->_action_key]);
- }
- // Set current id
- if(isset($this->_request_qry[$this->_id_key]))
- {
- $this->_id = preg_replace('/[^\w-:.]/', '', $this->_request_qry[$this->_id_key]);
- }
- $this->_posted_qry =& $_POST; //raw?
- return $this;
- }
- /**
- * Retrieve variable from GET scope
- * If $key is null, all GET data will be returned
- *
- * @param string $key [optional]
- * @param mixed $default [optional]
- * @return mixed
- */
- public function getQuery($key = null, $default = null)
- {
- if(null === $key)
- {
- return $this->_request_qry;
- }
- return (isset($this->_request_qry[$key]) ? $this->_request_qry[$key] : $default);
- }
- /**
- * Set/Unset GET variable
- * If $key is array, $value is not used.
- * If $value is null, (string) $key is unset
- *
- * @param string|array $key
- * @param mixed $value [optional]
- * @return e_admin_request
- */
- public function setQuery($key, $value = null)
- {
- if(is_array($key))
- {
- foreach ($key as $k=>$v)
- {
- $this->setQuery($k, $v);
- }
- return $this;
- }
- if(null === $value)
- {
- unset($this->_request_qry[$key]);
- unset($_GET[$key]);
- return $this;
- }
- $this->_request_qry[$key] = $value;
- $_GET[$key] = $value;
- return $this;
- }
- /**
- * Retrieve variable from POST scope
- * If $key is null, all POST data will be returned
- *
- * @param string $key [optional]
- * @param mixed $default [optional]
- * @return mixed
- */
- public function getPosted($key = null, $default = null)
- {
- if(null === $key)
- {
- return $this->_posted_qry;
- }
- return (isset($this->_posted_qry[$key]) ? $this->_posted_qry[$key] : $default);
- }
- /**
- * Set/Unset POST variable
- * If $key is array, $value is not used.
- * If $value is null, (string) $key is unset
- *
- * @param object $key
- * @param object $value [optional]
- * @return e_admin_request
- */
- public function setPosted($key, $value = null)
- {
- if(is_array($key))
- {
- if(empty($key))
- {
- $this->_posted_qry = array(); //POST reset
- return $this;
- }
- foreach ($key as $k=>$v)
- {
- $this->setPosted($k, $v);
- }
- return $this;
- }
- if(null === $value)
- {
- unset($this->_posted_qry[$key]);
- return $this;
- }
- $tp = e107::getParser();
- $this->_posted_qry[$tp->post_toForm($key)] = $tp->post_toForm($value);
- return $this;
- }
- /**
- * Get current mode
- * @return string
- */
- public function getMode()
- {
- if(!$this->_mode) return $this->getDefaultMode();
- return $this->_mode;
- }
- /**
- * Get default mode
- * @return string
- */
- public function getDefaultMode()
- {
- return $this->_default_mode;
- }
- /**
- * Get current mode name
- *
- * @return string
- */
- public function getModeName()
- {
- return strtolower(str_replace('-', '_', $this->getMode()));
- }
- /**
- * Reset current mode
- * @param string $mode
- * @return e_admin_request
- */
- public function setMode($mode)
- {
- $this->_mode = preg_replace('/[^\w]/', '', $mode);
- $this->setQuery($this->_mode_key, $this->_mode);
- return $this;
- }
- /**
- * Set default mode
- * @param string $mode
- * @return e_admin_request
- */
- public function setDefaultMode($mode)
- {
- if($mode) $this->_default_mode = $mode;
- return $this;
- }
- /**
- * Set mode key name
- * @param string $key
- * @return e_admin_request
- */
- public function setModeKey($key)
- {
- $this->_mode_key = $key;
- return $this;
- }
- /**
- * Get current action
- * @return TBD
- */
- public function getAction()
- {
- if(!$this->_action) return $this->getDefaultAction();
- return $this->_action;
- }
- /**
- * Get default action
- * @return string
- */
- public function getDefaultAction()
- {
- return $this->_default_action;
- }
- /**
- * Get current action name
- * @return string camelized action
- */
- public function getActionName()
- {
- return $this->camelize($this->getAction());
- }
- /**
- * Reset current action
- *
- * @param string $action
- * @return e_admin_request
- */
- public function setAction($action)
- {
- $this->_action = preg_replace('/[^\w]/', '', $action);
- $this->setQuery($this->_action_key, $this->_action);
- return $this;
- }
- /**
- * Set default action
- *
- * @param string $action
- * @return e_admin_request
- */
- public function setDefaultAction($action)
- {
- if($action) $this->_default_action = $action;
- return $this;
- }
- /**
- * Set action key name
- * @param string $key
- * @return e_admin_request
- */
- public function setActionKey($key)
- {
- $this->_action_key = $key;
- return $this;
- }
- /**
- * Get current ID
- * @return integer
- */
- public function getId()
- {
- return $this->_id;
- }
- /**
- * Reset current ID
- * @param string $id
- * @return e_admin_request
- */
- public function setId($id)
- {
- $id = intval($id);
- $this->_id = $id;
- $this->setQuery($this->_id_key, $id);
- return $this;
- }
- /**
- * Set id key name
- * @param string $key
- * @return e_admin_request
- */
- public function setIdKey($key)
- {
- $this->_id_key = $key;
- return $this;
- }
- /**
- * Build query string from current request array
- * NOTE: changing url separator to & ($encode==true) (thus URL XHTML compliance) works in PHP 5.1.2+ environment
- *
- * @param string|array $merge_with [optional] override request values
- * @param boolean $encode if true & separator will be used, all values will be http encoded, default true
- * @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
- * @param boolean $keepSpecial don't exclude special vars as 'mode' and 'action'
- * @return string url encoded query string
- */
- public function buildQueryString($merge_with = array(), $encode = true, $exclude_from_query = '', $keepSpecial = true)
- {
- $ret = $this->getQuery();
- //special case - exclude all current
- if(true === $exclude_from_query)
- {
- $exclude_from_query = array_keys($ret);
- }
- // to array
- if(is_string($exclude_from_query))
- {
- $exclude_from_query = array_map('trim', explode(',', $exclude_from_query));
- }
- if($exclude_from_query)
- {
- foreach ($exclude_from_query as $var)
- {
- if($keepSpecial && $var != $this->_action_key && $var != $this->_mode_key) unset($ret[$var]);
- }
- }
- if(is_string($merge_with))
- {
- parse_str($merge_with, $merge_with);
- }
- $ret = array_merge($ret, (array) $merge_with);
- $separator = '&';
- if($encode)
- {
- $separator = '&';
- //$ret = array_map('rawurlencode', $ret);
- }
- $ret = http_build_query($ret, 'numeric_', $separator);
- if(!$encode)
- {
- return rawurldecode($ret);
- }
- return $ret;
- }
- /**
- * Convert string to CamelCase
- *
- * @param string $str
- * @return string
- */
- public function camelize($str)
- {
- return implode('', array_map('ucfirst', explode('-', str_replace('_', '-', $str))));
- }
- }
- /**
- * TODO - front response parent, should do all the header.php work
- */
- class e_admin_response
- {
- /**
- * Body segments
- *
- * @var array
- */
- protected $_body = array();
- /**
- * Title segments
- *
- * @var unknown_type
- */
- protected $_title = array();
- /**
- * e107 meta title
- *
- * @var array
- */
- protected $_e_PAGETITLE = array();
- /**
- * e107 meta description
- *
- * @var array
- */
- protected $_META_DESCRIPTION = array();
- /**
- * e107 meta keywords
- *
- * @var array
- */
- protected $_META_KEYWORDS = array();
- /**
- * Render mods
- *
- * @var array
- */
- protected $_render_mod = array();
- /**
- * Meta title segment description
- *
- * @var string
- */
- protected $_meta_title_separator = ' - ';
- /**
- * Title segment separator
- *
- * @var string
- */
- protected $_title_separator = ' » ';
- /**
- * Constructor
- *
- */
- public function __construct()
- {
- $this->_render_mod['default'] = 'admin_page';
- }
- /**
- * Set body segments for a namespace
- *
- * @param string $content
- * @param string $namespace segment namesapce
- * @return e_admin_response
- */
- function setBody($content, $namespace = 'default')
- {
- $this->_body[$namespace] = $content;
- return $this;
- }
- /**
- * Append body segment to a namespace
- *
- * @param string $content
- * @param string $namespace segment namesapce
- * @return e_admin_response
- */
- function appendBody($content, $namespace = 'default')
- {
- if(!isset($this->_body[$namespace]))
- {
- $this->_body[$namespace] = array();
- }
- $this->_body[$namespace][] = $content;
- return $this;
- }
- /**
- * Prepend body segment to a namespace
- *
- * @param string $content
- * @param string $namespace segment namespace
- * @return e_admin_response
- */
- function prependBody($content, $namespace = 'default')
- {
- if(!isset($this->_body[$namespace]))
- {
- $this->_body[$namespace] = array();
- }
- $this->_body[$namespace] = array_merge(array($content), $this->_body[$namespace]);
- return $this;
- }
- /**
- * Get body segments from a namespace
- *
- * @param string $namespace segment namesapce
- * @param boolean $reset reset segment namespace
- * @param string|boolean $glue if false return array, else return string
- * @return string|array
- */
- function getBody($namespace = 'default', $reset = false, $glue = '')
- {
- $content = vartrue($this->_body[$namespace], array());
- if($reset)
- {
- $this->_body[$namespace] = array();
- }
- if(is_bool($glue))
- {
- return ($glue ? $content : implode('', $content));
- }
- return implode($glue, $content);
- }
- /**
- * Set title segments for a namespace
- *
- * @param string $title
- * @param string $namespace
- * @return e_admin_response
- */
- function setTitle($title, $namespace = 'default')
- {
- $this->_title[$namespace] = array($title);
- return $this;
- }
- /**
- * Append title segment to a namespace
- *
- * @param string $title
- * @param string $namespace segment namesapce
- * @return e_admin_response
- */
- function appendTitle($title, $namespace = 'default')
- {
- if(empty($title))
- {
- return $this;
- }
- if(!isset($this->_title[$namespace]))
- {
- $this->_title[$namespace] = array();
- }
- $this->_title[$namespace][] = $title;
- return $this;
- }
- /**
- * Prepend title segment to a namespace
- *
- * @param string $title
- * @param string $namespace segment namespace
- * @return e_admin_response
- */
- function prependTitle($title, $namespace = 'default')
- {
- if(empty($title))
- {
- return $this;
- }
- if(!isset($this->_title[$namespace]))
- {
- $this->_title[$namespace] = array();
- }
- $this->_title[$namespace] = array_merge(array($title), $this->_title[$namespace]);
- return $this;
- }
- /**
- * Get title segments from namespace
- *
- * @param string $namespace
- * @param boolean $reset
- * @param boolean|string $glue
- * @return unknown
- */
- function getTitle($namespace = 'default', $reset = false, $glue = ' ')
- {
- $content = array();
- if(isset($this->_title[$namespace]) && is_array($this->_title[$namespace]))
- {
- $content = $this->_title[$namespace];
- }
- if($reset)
- {
- unset($this->_title[$namespace]);
- }
- if(is_bool($glue) || empty($glue))
- {
- return ($glue ? $content : implode($this->_title_separator, $content));
- }
- $glue = deftrue('SEP',' - '); // Defined by admin theme. // admin-ui used only by bootstrap.
- return implode($glue, $content);
- // return $head. implode($glue, $content).$foot;
- }
- /**
- * Set render mode for a namespace
- *
- * @param string $render_mod
- * @param string $namespace
- * @return e_admin_response
- */
- function setRenderMod($render_mod, $namespace = 'default')
- {
- $this->_render_mod[$namespace] = $render_mod;
- return $this;
- }
- /**
- * Set render mode for namespace
- *
- * @param string $namespace
- * @return string
- */
- function getRenderMod($namespace = 'default')
- {
- return varset($this->_render_mod[$namespace], null);
- }
- /**
- * Add meta title, description and keywords segments
- *
- * @param string $meta property name
- * @param string $content meta content
- * @return e_admin_response
- */
- function addMetaData($meta, $content)
- {
- $tp = e107::getParser();
- $meta = '_' . $meta;
- if(isset($this->{$meta}) && !empty($content))
- {
- $this->{$meta}[] = strip_tags($content);
- }
- return $this;
- }
- /**
- * Add meta title segment
- *
- * @param string $title
- * @return e_admin_response
- */
- function addMetaTitle($title)
- {
- $this->addMetaData('e_PAGETITLE', $title);
- return $this;
- }
- /**
- * Add meta description segment
- *
- * @param string $description
- * @return e_admin_response
- */
- function addMetaDescription($description)
- {
- $this->addMetaData('META_DESCRIPTION', $description);
- return $this;
- }
- /**
- * Add meta keywords segment
- *
- * @param string $keyword
- * @return e_admin_response
- */
- function addMetaKeywords($keyword)
- {
- $this->addMetaData('META_KEYWORDS', $keyword);
- return $this;
- }
- /**
- * Send e107 meta-data
- *
- * @return e_admin_response
- */
- function sendMeta()
- {
- //HEADERF already included or meta content already sent
- if(e_AJAX_REQUEST || defined('HEADER_INIT') || defined('e_PAGETITLE'))
- return $this;
- if(!defined('e_PAGETITLE') && !empty($this->_e_PAGETITLE))
- {
- define('e_PAGETITLE', implode($this->_meta_title_separator, $this->_e_PAGETITLE));
- }
- if(!defined('META_DESCRIPTION') && !empty($this->_META_DESCRIPTION))
- {
- define('META_DESCRIPTION', implode(' ', $this->_META_DESCRIPTION));
- }
- if(!defined('META_KEYWORDS') && !empty($this->_META_KEYWORDS))
- {
- define('META_KEYWORDS', implode(', ', $this->_META_KEYWORDS));
- }
- return $this;
- }
- /**
- * Add content segment to the header namespace
- *
- * @param string $content
- * @return e_admin_response
- */
- function addHeaderContent($content)
- {
- $this->appendBody($content, 'header_content');
- return $this;
- }
- /**
- * Get page header namespace content segments
- *
- * @param boolean $reset
- * @param boolean $glue
- * @return string
- */
- function getHeaderContent($reset = true, $glue = "\n\n")
- {
- return $this->getBody('header_content', $reset, $glue);
- }
- /**
- * Switch to iframe mod
- * FIXME - implement e_IFRAME to frontend - header_default.php
- *
- * @return e_admin_response
- */
- function setIframeMod()
- {
- global $HEADER, $FOOTER, $CUSTOMHEADER, $CUSTOMFOOTER;
- $HEADER = $FOOTER = '';
- $CUSTOMHEADER = $CUSTOMFOOTER = array();
- //TODO generic $_GET to activate for any page of admin.
- // New
- if(!defined('e_IFRAME'))
- {
- define('e_IFRAME', true);
- }
- return $this;
- }
- /**
- * Send Response Output
- *
- * @param string $name segment
- * @param array $options valid keys are: messages|render|meta|return|raw|ajax
- * @return mixed
- */
- function send($name = 'default', $options = array())
- {
- if(is_string($options))
- {
- parse_str($options, $options);
- }
- // Merge with all available default options
- $options = array_merge(array(
- 'messages' => true,
- 'render' => true,
- 'meta' => false,
- 'return' => false,
- 'raw' => false,
- 'ajax' => false
- ), $options);
- $content = $this->getBody($name, true);
- $title = $this->getTitle($name, true);
- $return = $options['return'];
- if($options['ajax'] || e_AJAX_REQUEST)
- {
- $type = $options['ajax'] && is_string($options['ajax']) ? $options['ajax'] : '';
- $this->getJsHelper()->sendResponse($type);
- }
- if($options['messages'])
- {
- $content = e107::getMessage()->render().$content;
- }
- if($options['meta'])
- {
- $this->sendMeta();
- }
- // raw output expected - force return array
- if($options['raw'])
- {
- return array($title, $content, $this->getRenderMod($name));
- }
- //render disabled by the controller
- if(!$this->getRenderMod($name))
- {
- $options['render'] = false;
- }
- if($options['render'])
- {
- return e107::getRender()->tablerender($title, $content, $this->getRenderMod($name), $return);
- }
- if($return)
- {
- return $content;
- }
- print($content);
- return '';
- }
- /**
- * Get JS Helper instance
- *
- * @return e_jshelper
- */
- public function getJsHelper()
- {
- return e107::getSingleton('e_jshelper', true, 'admin_response');
- }
- }
- /**
- * TODO - request related code should be moved to core
- * request handler
- */
- class e_admin_dispatcher
- {
- /**
- * @var e_admin_request
- */
- protected $_request = null;
- /**
- * @var e_admin_response
- */
- protected $_response = null;
- /**
- * @var e_admin_controller
- */
- protected $_current_controller = null;
- /**
- * Required (set by child class).
- * Controller map array in format
- * 'MODE' => array('controller' =>'CONTROLLER_CLASS_NAME'[, 'path' => 'CONTROLLER SCRIPT PATH', 'ui' => extend of 'comments_admin_form_ui', 'uipath' => 'path/to/ui/']);
- *
- * @var array
- */
- protected $modes = array();
-
- /**
- * Optional - access restrictions per action
- * Access array in format (similar to adminMenu)
- * 'MODE/ACTION' => e_UC_* (userclass constant, or custom userclass ID if dynamically set)
- *
- * @var array
- */
- protected $access = array();
-
- /**
- * Optional - generic entry point access restriction (via getperms())
- * Value of this for plugins would be always 'P'.
- * More detailed access control is granted with $access and $modes[MODE]['perm'] or $modes[MODE]['userclass'] settings
- *
- * @var string
- */
- protected $perm;
- /**
- * @var string
- */
- protected $defaultMode = '';
- /**
- * @var string
- */
- protected $defaultAction = '';
- /**
- * Optional - map 'mode/action' pair to 'modeAlias/actionAlias'
- * @var string
- */
- protected $adminMenuAliases = array();
- /**
- * Optional (set by child class).
- * Required for admin menu render
- * Format: 'mode/action' => array('caption' => 'Link title'[, 'perm' => '0', 'url' => '{e_PLUGIN}plugname/admin_config.php'], ...);
- * Note that 'perm' and 'userclass' restrictions are inherited from the $modes, $access and $perm, so you don't have to set that vars if
- * you don't need any additional 'visual' control.
- * All valid key-value pair (see e107::getNav()->admin function) are accepted.
- * @var array
- */
- protected $adminMenu = array();
-
- /**
- * Optional (set by child class).
- * Page titles for pages not in adminMenu (e.g. main/edit)
- * Format array(mod/action => Page Title)
- * @var string
- */
- protected $pageTitles = array(
- 'main/edit' => LAN_MANAGE,
- );
- /**
- * Optional (set by child class).
- * @var string
- */
- protected $menuTitle = 'Menu';
- /**
- * @var string
- */
- protected $pluginTitle = '';
- /**
- * Constructor
- *
- * @param string|array|e_admin_request $request [optional]
- * @param e_admin_response $response
- */
- public function __construct($auto_observe = true, $request = null, $response = null)
- {
- // we let know some admin routines we are in UI mod - related with some legacy checks and fixes
- if(!defined('e_ADMIN_UI'))
- {
- define('e_ADMIN_UI', true);
- }
- require_once(e_ADMIN.'boot.php');
-
- if(null === $request || !is_object($request))
- {
- $request = new e_admin_request($request);
- }
- if(null === $response)
- {
- $response = new e_admin_response();
- }
- $this->setRequest($request)->setResponse($response)->init();
- if(!$this->defaultMode || !$this->defaultAction)
- {
- $this->setDefaults();
- }
- $request->setDefaultMode($this->defaultMode)->setDefaultAction($this->defaultAction);
- // register itself
- e107::setRegistry('admin/ui/dispatcher', $this);
-
- // permissions and restrictions
- $this->checkAccess();
- if($auto_observe)
- {
- $this->runObservers(true);
- }
- }
- /**
- * User defined constructor - called before _initController() method
- * @return e_admin_dispatcher
- */
- public function init()
- {
- }
-
- public function checkAccess()
- {
- $request = $this->getRequest();
- $currentMode = $request->getMode();
- // access based on mode setting - general controller access
- if(!$this->checkModeAccess($currentMode))
- {
- $request->setAction('e403');
- e107::getMessage()->addError('You don\'t have permissions to view this page.')
- ->addDebug('Mode access restriction triggered.');
- return false;
- }
-
- // access based on $access settings - access per action
- $currentAction = $request->getAction();
- $route = $currentMode.'/'.$currentAction;
- if(!$this->checkRouteAccess($route))
- {
- $request->setAction('e403');
- e107::getMessage()->addError('You don\'t have permissions to view this page.')
- ->addDebug('Route access restriction triggered.');
- return false;
- }
-
- return true;
- }
-
- public function checkModeAccess($mode)
- {
- // mode userclass (former check_class())
- if(isset($this->modes[$mode]['userclass']) && !e107::getUser()->checkClass($this->modes[$mode]['userclass'], false))
- {
- return false;
- }
- // mode admin permission (former getperms())
- if(isset($this->modes[$mode]['perm']) && !e107::getUser()->checkAdminPerms($this->modes[$mode]['perm']))
- {
- return false;
- }
- // generic dispatcher admin permission (former getperms())
- if(null !== $this->perm && !e107::getUser()->checkAdminPerms($this->perm))
- {
- return false;
- }
- return true;
- }
-
- public function checkRouteAccess($route)
- {
- if(isset($this->access[$route]) && !e107::getUser()->checkClass($this->access[$route], false))
- {
- return false;
- }
- return true;
- }
- /**
- * Retrieve missing default action/mode
- * @return e_admin_dispatcher
- */
- public function setDefaults()
- {
- // try Admin menu first
- if($this->adminMenu)
- {
- reset($this->adminMenu);
- list($mode, $action) = explode('/', key($this->adminMenu), 3);
- }
- else
- {
- reset($this->modes);
- $mode = key($this->modes);
- $action = $this->modes[$mode]['index'];
- }
- if(!$this->defaultMode) $this->defaultMode = $mode;
- if(!$this->defaultAction) $this->defaultAction = $action;
- return $this;
- }
- /**
- * Get admin menu array
- * @return array
- */
- public function getMenuData()
- {
- return $this->adminMenu;
- }
-
- /**
- * Get admin menu array
- * @return array
- */
- public function getPageTitles()
- {
- return $this->pageTitles;
- }
- /**
- * Get admin menu array
- * @return array
- */
- public function getMenuAliases()
- {
- return $this->adminMenuAliases;
- }
- /**
- * Get request object
- * @return e_admin_request
- */
- public function getRequest()
- {
- return $this->_request;
- }
- /**
- * Set request object
- * @param e_admin_request $request
- * @return e_admin_dispatcher
- */
- public function setRequest($request)
- {
- $this->_request = $request;
- return $this;
- }
- /**
- * Get response object
- * @return e_admin_response
- */
- public function getResponse()
- {
- return $this->_response;
- }
- /**
- * Set response object
- * @param e_admin_response $response
- * @return e_admin_dispatcher
- */
- public function setResponse($response)
- {
- $this->_response = $response;
- return $this;
- }
- /**
- * Dispatch & render all
- *
- * @param boolean $run_header see runObservers()
- * @param boolean $return see runPage()
- * @return string|array current admin page body
- */
- public function run($run_header = true, $return = 'render')
- {
- return $this->runObservers()->runPage($return);
- }
- /**
- * Run observers/headers only, should be called before header.php call
- *
- * @return e_admin_dispatcher
- */
- public function runObservers($run_header = true)
- {
- //search for $actionName.'Observer' method. Additional $actionName.$triggerName.'Trigger' methods will be called as well
- $this->getController()->dispatchObserver();
- //search for $actionName.'Header' method, js manager should be used inside for sending JS to the page,
- // meta information should be created there as well
- if($run_header)
- {
- $this->getController()->dispatchHeader();
- }
- return $this;
- }
- /**
- * Run page action.
- * If return type is array, it should contain allowed response options (see e_admin_response::send())
- * Available return type string values:
- * - render_return: return rendered content ( see e107::getRender()->tablerender()), add system messages, send meta information
- * - render: outputs rendered content ( see e107::getRender()->tablerender()), add system messages
- * - response: return response object
- * - raw: return array(title, content, render mode)
- * - ajax: force ajax output (and exit)
- *
- * @param string|array $return_type expected string values: render|render_out|response|raw|ajax[_text|_json|_xml]
- * @return mixed
- */
- public function runPage($return_type = 'render')
- {
- $response = $this->getController()->dispatchPage();
- if(is_array($return_type))
- {
- return $response->send('default', $return_type);
- }
- switch($return_type)
- {
- case 'render_return':
- $options = array(
- 'messages' => true,
- 'render' => true,
- 'meta' => true,
- 'return' => true,
- 'raw' => false
- );
- break;
- case 'raw':
- $options = array(
- 'messages' => false,
- 'render' => false,
- 'meta' => false,
- 'return' => true,
- 'raw' => true
- );
- break;
- case 'ajax':
- case 'ajax_text':
- case 'ajax_xml';
- case 'ajax_json';
- $options = array(
- 'messages' => false,
- 'render' => false,
- 'meta' => false,
- 'return' => false,
- 'raw' => false,
- 'ajax' => str_replace(array('ajax_', 'ajax'), array('', 'text'), $return_type)
- );
- break;
- case 'response':
- return $response;
- break;
- case 'render':
- default:
- $options = array(
- 'messages' => true,
- 'render' => true,
- 'meta' => false,
- 'return' => false,
- 'raw' => false
- );
- break;
- }
- return $response->send('default', $options);
- }
- /**
- * Proxy method
- *
- * @return string
- */
- public function getHeader()
- {
- return $this->getController()->getHeader();
- }
- /**
- * Get current controller object
- * @return e_admin_controller
- */
- public function getController()
- {
- if(null === $this->_current_controller)
- {
- $this->_initController();
- }
- return $this->_current_controller;
- }
- /**
- * Try to init Controller from request using current controller map
- *
- * @return e_admin_dispatcher
- */
- protected function _initController()
- {
- $request = $this->getRequest();
- $response = $this->getResponse();
- if(isset($this->modes[$request->getModeName()]) && isset($this->modes[$request->getModeName()]['controller']))
- {
- $class_name = $this->modes[$request->getModeName()]['controller'];
- $class_path = vartrue($this->modes[$request->getModeName()]['path']);
- if($class_path)
- {
- require_once(e107::getParser()->replaceConstants($class_path));
- }
- if($class_name && class_exists($class_name))//NOTE: autoload in the play
- {
- $this->_current_controller = new $class_name($request, $response);
- //give access to current request object, user defined init
- $this->_current_controller->setRequest($this->getRequest())->init();
- }
- // Known controller (found in e_admin_dispatcher::$modes), class not found exception
- else
- {
- // TODO - admin log
- // get default controller
- $this->_current_controller = $this->getDefaultController();
- // add messages
- e107::getMessage()->add('Can\'t find class <strong>"'.($class_name ? $class_name : 'n/a').'"</strong> for controller <strong>"'.ucfirst($request->getModeName()).'"</strong>', E_MESSAGE_ERROR)
- ->add('Requested: '.e_SELF.'?'.$request->buildQueryString(), E_MESSAGE_DEBUG);
- //
- $request->setMode($this->getDefaultControllerName())->setAction('e404');
- $this->_current_controller->setRequest($request)->init();
- }
- if(vartrue($this->modes[$request->getModeName()]['ui']))
- {
- $class_name = $this->modes[$request->getModeName()]['ui'];
- $class_path = vartrue($this->modes[$request->getModeName()]['uipath']);
- if($class_path)
- {
- require_once(e107::getParser()->replaceConstants($class_path));
- }
- if(class_exists($class_name))//NOTE: autoload in the play
- {
- $this->_current_controller->setParam('ui', new $class_name($this->_current_controller));
- }
- }
- $this->_current_controller->setParam('modes', $this->modes);
- }
- // Not known controller (not found in e_admin_dispatcher::$modes) exception
- else
- {
- // TODO - admin log
- $this->_current_controller = $this->getDefaultController();
- // add messages
- e107::getMessage()->add('Can\'t find class for controller <strong>"'.ucfirst($request->getModeName()).'"</strong>', E_MESSAGE_ERROR)
- ->add('Requested: '.e_SELF.'?'.$request->buildQueryString(), E_MESSAGE_DEBUG);
- // go to not found page
- $request->setMode($this->getDefaultControllerName())->setAction('e404');
- $this->_current_controller->setRequest($request)->init();
- }
- return $this;
- }
- /**
- * Default controller object - needed if controller not found
- * @return e_admin_controller
- */
- public function getDefaultController()
- {
- $class_name = $this->getDefaultControllerName();
- return new $class_name($this->getRequest(), $this->getResponse());
- }
- /**
- * Default controller name - needed if controller not found
- * @return string name of controller
- */
- public function getDefaultControllerName()
- {
- return 'e_admin_controller';
- }
- /**
- * Generic Admin Menu Generator
- * @return string
- */
- function renderMenu()
- {
-
- $tp = e107::getParser();
- $var = array();
- $selected = false;
- foreach($this->adminMenu as $key => $val)
- {
- $tmp = explode('/', trim($key, '/'), 3);
- // sync with mode/route access
- if(!$this->checkModeAccess($tmp[0]) || !$this->checkRouteAccess($tmp[0].'/'.$tmp[1]))
- {
- continue;
- }
- // custom 'selected' check
- if(isset($val['selected']) && $val['selected']) $selected = $val['selected'] === true ? $key : $val['selected'];
- foreach ($val as $k=>$v)
- {
- switch($k)
- {
- case 'caption':
- $k2 = 'text';
- $v = defset($v, $v);
- break;
- case 'url':
- $k2 = 'link';
- $v = $tp->replaceConstants($v, 'abs').'?mode='.$tmp[0].'&action='.$tmp[1];
- break;
- case 'uri':
- $k2 = 'link';
- $v = $tp->replaceConstants($v, 'abs');
- break;
- default:
- $k2 = $k;
-
- break;
- }
-
- // Access check done above
- // if($val['perm']!= null) // check perms
- // {
- // if(getperms($val['perm']))
- // {
- // $var[$key][$k2] = $v;
- // }
- // }
- // else
- {
- $var[$key][$k2] = $v;
-
- }
- }
-
-
-
- // TODO slide down menu options?
- if(!vartrue($var[$key]['link']))
- {
- $var[$key]['link'] = e_SELF.'?mode='.$tmp[0].'&action='.$tmp[1]; // FIXME - URL based on $modes, remove url key
- }
-
- if(varset($val['tab']))
- {
- $var[$key]['link'] .= "&tab=".$val['tab'];
- }
- /*$var[$key]['text'] = $val['caption'];
- $var[$key]['link'] = (vartrue($val['url']) ? $tp->replaceConstants($val['url'], 'abs') : e_SELF).'?mode='.$tmp[0].'&action='.$tmp[1];
- $var[$key]['perm'] = $val['perm']; */
- }
-
- if(empty($var)) return '';
-
- $request = $this->getRequest();
- if(!$selected) $selected = $request->getMode().'/'.$request->getAction();
- $selected = vartrue($this->adminMenuAliases[$selected], $selected);
- return e107::getNav()->admin($this->menuTitle, $selected, $var);
- }
- /**
- * Render Help Text in <ul> format. XXX TODO
- */
- function renderHelp()
- {
-
-
-
- }
-
- /**
- * Check for table issues and warn the user. XXX TODO
- * ie. user is using French interface but no french tables found for the current DB tables.
- */
- function renderWarnings()
- {
-
-
-
-
- }
-
- }
- class e_admin_controller
- {
- /**
- * @var e_admin_request
- */
- protected $_request;
- /**
- * @var e_admin_response
- */
- protected $_response;
- /**
- * @var array User defined parameters
- */
- protected $_params = array();
- /**
- * @var string default action name
- */
- protected $_default_action = 'index';
-
- /**
- * List (numerical array) of only allowed for this controller actions
- * Useful to grant access for certain pre-defined actions only
- * XXX - we may move this in dispatcher (or even having it also there), still searching the most 'friendly' way
- * @var array
- */
- protected $allow = array();
-
- /**
- * List (numerical array) of only disallowed for this controller actions
- * Useful to restrict access for certain pre-defined actions only
- * XXX - we may move this in dispatcher (or even having it also there), still searching the most 'friendly' way
- * @var array
- */
- protected $disallow = array();
- /**
- * Constructor
- * @param e_admin_request $request [optional]
- */
- public function __construct($request, $response, $params = array())
- {
- $this->_params = array_merge(array('enable_triggers' => false), $params);
- $this->setRequest($request)
- ->setResponse($response)
- ->setParams($params);
-
- $this->checkAccess();
- }
- /**
- * Check against allowed/disallowed actions
- * FIXME check plugin admin access (check_class(P)), confirm e-token is verified
- */
- public function checkAccess()
- {
- $request = $this->getRequest();
- $currentAction = $request->getAction();
- // access based on mode setting - general controller access
- if(!empty($this->disallow) && in_array($currentAction, $this->disallow))
- {
- $request->setAction('e403');
- e107::getMessage()->addError('You don\'t have permissions to view this page.')
- ->addDebug('Controller action disallowed restriction triggered.');
- return false;
- }
-
- // access based on $access settings - access per action
- if(!empty($this->allow) && !in_array($currentAction, $this->allow))
- {
- $request->setAction('e403');
- e107::getMessage()->addError('You don\'t have permissions to view this page.')
- ->addDebug('Controller action not in allowed list restriction triggered.');
- return false;
- }
- return true;
- }
- /**
- * User defined init
- * Called before dispatch routine
- */
- public function init()
- {
- }
- /**
- * Get controller parameter
- * Currently used core parameters:
- * - enable_triggers: don't use it direct, see {@link setTriggersEnabled()}
- * - modes - see dispatcher::$modes
- * - ajax_response - text|xml|json - default is 'text'; this should be set by the action method
- * - TODO - more parameters/add missing to this list
- *
- * @param string $key [optional] if null - get whole array
- * @param mixed $default [optional]
- * @return mixed
- */
- public function getParam($key = null, $default = null)
- {
- if(null === $key)
- {
- return $this->_params;
- }
- return (isset($this->_params[$key]) ? $this->_params[$key] : $default);
- }
- /**
- * Set parameter
- * @param string $key
- * @param mixed $value
- * @return e_admin_controller
- */
- public function setParam($key, $value)
- {
- if(null === $value)
- {
- unset($this->_params[$key]);
- return $this;
- }
- $this->_params[$key] = $value;
- return $this;
- }
- /**
- * Merge passed parameter array with current parameters
- * @param array $params
- * @return e_admin_controller
- */
- public function setParams($params)
- {
- $this->_params = array_merge($this->_params, $params);
- return $this;
- }
- /**
- * Reset parameter array
- * @param array $params
- * @return e_admin_controller
- */
- public function resetParams($params)
- {
- $this->_params = $params;
- return $this;
- }
- /**
- * Get current request object
- * @return e_admin_request
- */
- public function getRequest()
- {
- return $this->_request;
- }
- /**
- * Set current request object
- * @param e_admin_request $request
- * @return e_admin_controller
- */
- public function setRequest($request)
- {
- $this->_request = $request;
- return $this;
- }
- /**
- * Get current response object
- * @return e_admin_response
- */
- public function getResponse()
- {
- return $this->_response;
- }
- /**
- * Set current response object
- * @param e_admin_response $response
- * @return e_admin_controller
- */
- public function setResponse($response)
- {
- $this->_response = $response;
- return $this;
- }
-
- /**
- * Get current dispatcher object
- * @return e_admin_dispatcher
- */
- public function getDispatcher()
- {
- return e107::getRegistry('admin/ui/dispatcher');
- }
- /**
- * Request proxy method
- * @param string $key [optional]
- * @param mixed $default [optional]
- * @return mixed
- */
- public function getQuery($key = null, $default = null)
- {
- return $this->getRequest()->getQuery($key, $default);
- }
- /**
- * Request proxy method
- * @param string|array $key
- * @param mixed $value [optional]
- * @return e_admin_controller
- */
- public function setQuery($key, $value = null)
- {
- $this->getRequest()->setQuery($key, $value);
- return $this;
- }
- /**
- * Request proxy method
- * @param string $key [optional]
- * @param mixed $default [optional]
- * @return mixed
- */
- public function getPosted($key = null, $default = null)
- {
- return $this->getRequest()->getPosted($key, $default);
- }
- /**
- * Request proxy method
- * @param string $key
- * @param mixed $value [optional]
- * @return e_admin_controller
- */
- public function setPosted($key, $value = null)
- {
- $this->getRequest()->setPosted($key, $value);
- return $this;
- }
- /**
- * Add page title, response proxy method
- *
- * @param string $title if boolean true - current menu caption will be used
- * @param boolean $meta add to meta as well
- * @return e_admin_controller
- */
- public function addTitle($title = true, $meta = true)
- {
- if(true === $title)
- {
- $_dispatcher = $this->getDispatcher();
- $data = $_dispatcher->getPageTitles();
- $search = $this->getMode().'/'.$this->getAction();
- if(isset($data[$search])) $res['caption'] = $data[$search];
- else
- {
- $data = $_dispatcher->getMenuData();
- if(isset($data[$search])) $res = $data[$search];
- else return $this;
- }
- $title = $res['caption'];
- }
- // print_a($title);
- $this->getResponse()->appendTitle($title);
- if($meta) $this->addMetaTitle($title);
- return $this;
- }
- /**
- * Add page meta title, response proxy method.
- * Should be called before header.php
- *
- * @param string $title
- * @return e_admin_controller
- */
- public function addMetaTitle($title)
- {
- $this->getResponse()->addMetaTitle($title);
- return $this;
- }
- /**
- * Add header content, response proxy method
- * Should be called before header.php
- *
- * @param string $content
- * @return e_admin_controller
- */
- public function addHeader($content)
- {
- $this->getResponse()->addHeaderContent(vartrue($content));
- return $this;
- }
- /**
- * Get header content, response proxy method
- *
- * @return string
- */
- public function getHeader()
- {
- return $this->getResponse()->getHeaderContent();
- }
- /**
- * Get current mode, response proxy method
- * @return string
- */
- public function getMode()
- {
- return $this->getRequest()->getMode();
- }
- /**
- * Get current actin, response proxy method
- * @return string
- */
- public function getAction()
- {
- return $this->getRequest()->getAction();
- }
- /**
- * Get current ID, response proxy method
- * @return string
- */
- public function getId()
- {
- return $this->getRequest()->getId();
- }
- /**
- * Get response owned JS Helper instance, response proxy method
- *
- * @return e_jshelper
- */
- public function getJsHelper()
- {
- return $this->getResponse()->getJsHelper();
- }
- protected function _preDispatch($action = '')
- {
- if(!$action) $action = $this->getRequest()->getActionName();
- $method = $this->toMethodName($action, 'page');
- if(!method_exists($this, $method))
- {
- $this->getRequest()->setAction($this->getDefaultAction());
- }
- // switch to 404 if needed
- $method = $this->toMethodName($this->getRequest()->getActionName(), 'page');
- if(!method_exists($this, $method))
- {
- $this->getRequest()->setAction('e404');
- $message = e107::getParser()->lanVars(LAN_UI_404_METHOD_ERROR, $method, true);
- e107::getMessage()->add($message, E_MESSAGE_ERROR);
- }
- }
- /**
- * Dispatch observer, check for triggers
- *
- * @param string $action [optional]
- * @return e_admin_controller
- */
- public function dispatchObserver($action = null)
- {
- $request = $this->getRequest();
- if(null === $request)
- {
- $request = new e_admin_request();
- $this->setRequest($request);
- }
- $this->_preDispatch($action);
- if(null === $action)
- {
- $action = $request->getActionName();
- }
- // check for observer
- $actionObserverName = $this->toMethodName($action, 'observer', e_AJAX_REQUEST);
- if(method_exists($this, $actionObserverName))
- {
- $this->$actionObserverName();
- }
- // check for triggers, not available in Ajax mode
- if(!e_AJAX_REQUEST && $this->triggersEnabled())
- {
- $posted = $request->getPosted();
- foreach ($posted as $key => $value)
- {
- if(strpos($key, 'etrigger_') === 0)
- {
- $actionTriggerName = $this->toMethodName($action.$request->camelize(substr($key, 9)), 'trigger', false);
- if(method_exists($this, $actionTriggerName))
- {
- $this->$actionTriggerName($value);
- }
- //Check if triggers are still enabled
- if(!$this->triggersEnabled())
- {
- break;
- }
- }
- }
- }
- return $this;
- }
- /**
- * Dispatch header, not allowed in Ajax mode
- * @param string $action [optional]
- * @return e_admin_controller
- */
- public function dispatchHeader($action = null)
- {
- // not available in Ajax mode
- if(e_AJAX_REQUEST)
- {
- return $this;
- }
- $request = $this->getRequest();
- if(null === $request)
- {
- $request = new e_admin_request();
- $this->setRequest($request);
- }
- $this->_preDispatch($action);
- if(null === $action)
- {
- $action = $request->getActionName();
- }
- // check for observer
- $actionHeaderName = $this->toMethodName($action, 'header', false);
- if(method_exists($this, $actionHeaderName))
- {
- $this->$actionHeaderName();
- }
- //send meta data
- $this->getResponse()->sendMeta();
- return $this;
- }
- /**
- * Dispatch controller action
- *
- * @param string $action [optional]
- * @return e_admin_response
- */
- public function dispatchPage($action = null)
- {
- $request = $this->getRequest();
- if(null === $request)
- {
- $request = new e_admin_request();
- $this->setRequest($request);
- }
- $response = $this->getResponse();
- $this->_preDispatch($action);
- if(null === $action)
- {
- $action = $request->getActionName();
- }
- // check for observer
- $actionName = $this->toMethodName($action, 'page');
- $ret = '';
- if(!method_exists($this, $actionName)) // pre dispatch already switched to default action/not found page if needed
- {
- e107::getMessage()->add('Action '.$actionName.' no found!', E_MESSAGE_ERROR);
- return $response;
- }
- ob_start(); //catch any output
- $ret = $this->{$actionName}();
- //Ajax XML/JSON communication
- if(e_AJAX_REQUEST && is_array($ret))
- {
- $response_type = $this->getParam('ajax_response', 'xml');
- ob_clean();
- $js_helper = $response->getJsHelper();
- foreach ($ret as $act => $data)
- {
- $js_helper->addResponse($data, $act);
- }
- $js_helper->sendResponse($response_type);
- }
- $ret .= ob_get_clean();
- // Ajax text response
- if(e_AJAX_REQUEST)
- {
- $response_type = 'text';
- $response->getJsHelper()->addResponse($ret)->sendResponse($response_type);
- }
- else
- {
- $response->appendBody($ret);
- }
- return $response;
- }
- public function E404Observer()
- {
- $this->getResponse()->setTitle(LAN_UI_404_TITLE_ERROR);
- }
- public function E404Page()
- {
- return '<div class="center">'.LAN_UI_404_BODY_ERROR.'</div>'; // TODO - lan
- }
- public function E404AjaxPage()
- {
- exit;
- }
-
- public function E403Observer()
- {
- $this->getResponse()->setTitle(LAN_UI_403_TITLE_ERROR);
- }
- public function E403Page()
- {
- return '<div class="center">'.LAN_UI_403_BODY_ERROR.'</div>'; // TODO - lan
- }
- public function E403AjaxPage()
- {
- exit;
- }
- /**
- * Generic redirect handler, it handles almost everything we would need.
- * Additionally, it moves currently registered system messages to SESSION message stack
- * In almost every case {@link redirectAction()} and {@link redirectMode()} are better solution
- *
- * @param string $action defaults to current action
- * @param string $mode defaults to current mode
- * @param string|array $exclude_query comma delimited variable names to be excluded from current query OR TRUE to exclude everything
- * @param string|array $merge_query query string (& delimiter) or associative array to be merged with current query
- * @param string $path default to e_SELF
- * @return void
- */
- public function redirect($action = null, $mode = null, $exclude_query = '', $merge_query = array(), $path = null)
- {
- $request = $this->getRequest();
- if($mode) $request->setMode($mode);
- if($action) $request->setAction($action);
- if(!$path) $path = e_SELF;
-
- //prevent cache
- header('Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
- // header('Pragma: no-cache');
- $url = $path.'?'.$request->buildQueryString($merge_query, false, $exclude_query);
- // Transfer all messages to session
- e107::getMessage()->moveToSession();
- // write session data
- session_write_close();
- // do redirect
- header('Location: '.$url);
- exit;
- }
- /**
- * Convenient redirect() proxy method, make life easier when redirecting between actions
- * in same mode.
- *
- * @param string $action [optional]
- * @param string|array $exclude_query [optional]
- * @param string|array $merge_query [optional]
- * @return none
- */
- public function redirectAction($action = null, $exclude_query = '', $merge_query = array())
- {
- $this->redirect($action, null, $exclude_query, $merge_query);
- }
- /**
- * Convenient redirect to another mode (doesn't use current Query state)
- * If path is empty, it'll be auto-detected from modes (dispatcher) array
- *
- * @param string $mode
- * @param string $action
- * @param string|array $query [optional]
- * @param string $path
- * @return void
- */
- public function redirectMode($mode, $action, $query = array(), $path = null)
- {
- if(!$path && $this->getParam('modes'))
- {
- $modes = $this->getParam('modes');
- if(vartue($modes[$mode]) && vartrue($modes[$mode]['url']))
- {
- $path = e107::getParser()->replaceConstants($modes[$mode]['url'], 'abs');
- }
- }
- $this->redirect($action, $mode, true, $query, $path);
- }
- /**
- * Convert action name to method name
- *
- * @param string $action_name formatted (e.g. request method getActionName()) action name
- * @param string $type page|observer|header|trigger
- * @param boolean $ajax force with true/false, if null will be auto-resolved
- * @return string
- */
- public function toMethodName($action_name, $type= 'page', $ajax = null)
- {
- if(null === $ajax) $ajax = e_AJAX_REQUEST; //auto-resolving
- return $action_name.($ajax ? 'Ajax' : '').ucfirst(strtolower($type));
- }
- /**
- * Check if there is a trigger available in the posted data
- * @param array $exclude
- * @return boolean
- */
- public function hasTrigger($exclude = array())
- {
- $posted = array_keys($this->getPosted());
- foreach ($posted as $key)
- {
- if(!in_array($key, $exclude) && strpos($key, 'etrigger_') === 0)
- {
- return true;
- }
- }
- return false;
- }
- /**
- * Get default action
- * @return string action
- */
- public function getDefaultAction()
- {
- return $this->_default_action;
- }
- /**
- * Set default action
- * @param string $action_name
- * @return e_admin_controller
- */
- public function setDefaultAction($action_name)
- {
- $this->_default_action = $action_name;
- return $this;
- }
- /**
- * @return boolean
- */
- public function triggersEnabled()
- {
- return $this->getParam('enable_triggers');
- }
- /**
- * @param boolean $flag
- * @return e_admin_controller
- */
- public function setTriggersEnabled($flag)
- {
- $this->setParam('enable_triggers', $flag);
- return $this;
- }
- }
- //FIXME - move everything from e_admin_ui except model auto-create related code
- class e_admin_controller_ui extends e_admin_controller
- {
- /**
- * @var array UI field data
- */
- protected $fields = array();
- /**
- * @var array default fields activated on List view
- */
- protected $fieldpref = array();
- /**
- * @var array Plugin Preference description array
- */
- protected $prefs = array();
- /**
- * Data required for _modifyListQry() to automate
- * db query building
- * @var array
- */
- protected $tableJoin = array();
- /**
- * Array of table names and their aliases. (detected from listQry)
- * db query building
- * @var array
- */
- protected $joinAlias = array();
- /**
- * Array of fields detected from listQry which are JOINs
- * @example returns array('user_name'=>'u.user_name'); from $listQry = "SELECT n.*,u.user_name FROM #news...."etc.
- */
- protected $joinField = array();
- /**
- * Main model table alias
- * @var string
- */
- protected $tableAlias;
- /**
- * @var string plugin name
- */
- protected $pluginName;
- /**
- * @var string
- */
- protected $defaultOrderField = null;
- /**
- * @var string
- */
- protected $defaultOrder = 'asc';
- /**
- * @var string SQL order, false to disable order, null is default order
- */
- protected $listOrder = null;
-
- /**
- * @var string field containing the order number
- */
- protected $sortField = null;
-
- /**
- * @var int reorder step
- */
- protected $orderStep = 1;
-
- /**
- * Example: array('0' => 'Tab label', '1' => 'Another label');
- * Referenced from $field property per field - 'tab => xxx' where xxx is the tab key (identifier)
- * @var array edit/create form tabs
- */
- protected $tabs = array();
-
- /**
- * Example: array('0' => 'Tab label', '1' => 'Another label');
- * Referenced from $prefs property per field - 'tab => xxx' where xxx is the tab key (identifier)
- * @var array edit/create form tabs
- */
- protected $preftabs = array();
-
- /**
- * TODO Example:
- * Contains required data for auto-assembling URL from every record
- * For greater control - override url() method
- * @var array
- */
- protected $url = array();
-
- /**
- * TODO Example:
- * Contains required data for mapping featurebox fields
- * @var array
- */
- protected $featurebox = array();
- /**
- * Structure same as TreeModel parameters used for building the load() SQL
- * @var additional SQL to be applied when auto-building the list query
- */
- protected $listQrySql = array();
-
- /**
- * @var Custom Filter SQL Query override.
- */
- protected $filterQry = null;
- /**
- * @var boolean
- */
- protected $batchDelete = true;
-
- /**
- * @var boolean
- */
- protected $batchCopy = false;
-
- /**
- * @var boolean
- */
- protected $batchLink = false;
-
- /**
- * @var boolean
- */
- protected $batchFeaturebox = false;
-
- /**
- * Could be LAN constant (mulit-language support)
- *
- * @var string plugin name
- */
- protected $pluginTitle;
- /**
- * Default (db) limit value
- * @var integer
- */
- protected $perPage = 20;
-
- /**
- * @var e_admin_model
- */
- protected $formQuery = false; // custom form post query
- /**
- * @var e_admin_model
- */
- protected $_model = null;
- /**
- * @var e_admin_tree_model
- */
- protected $_tree_model = null;
- /**
- * @var e_admin_tree_model
- */
- protected $_ui = null;
- /**
- * @var e_plugin_pref|e_core_pref
- */
- protected $_pref = null;
-
- /**
- * Prevent parsing table aliases more than once
- * @var boolean
- */
- protected $_alias_parsed = false;
- public function getBatchDelete()
- {
- return $this->batchDelete;
- }
-
- public function getBatchCopy()
- {
- return $this->batchCopy;
- }
-
-
- public function getBatchLink()
- {
- return $this->batchLink;
- }
- public function getBatchFeaturebox()
- {
- return $this->batchFeaturebox;
- }
-
-
- /**
- * @return string
- */
- public function getPluginName()
- {
- return $this->pluginName;
- }
- /**
- * @return string
- */
- public function getPluginTitle()
- {
- return deftrue($this->pluginTitle, $this->pluginTitle);
- }
-
- /**
- * Get Tab data
- * @return array
- */
- public function getTabs()
- {
- return $this->tabs;
- }
-
- /**
- * Get Tab data
- * @return array
- */
- public function getPrefTabs()
- {
- return $this->preftabs;
- }
- /**
- * Get URL profile
- * @return array
- */
- public function getUrl()
- {
- return $this->url;
- }
-
- /**
- * Get Featurebox Copy
- * @return array
- */
- public function getFeaturebox()
- {
- return $this->featurebox;
- }
- /**
- * Get all field data
- * @return array
- */
- public function getFields()
- {
- return $this->fields;
- }
- /**
- *
- * @param string $field
- * @param string $key attribute name
- * @param mixed $default default value if not set, default is null
- * @return mixed
- */
- public function getFieldAttr($field, $key = null, $default = null)
- {
- if(isset($this->fields[$field]))
- {
- if(null !== $key)
- {
- return isset($this->fields[$field][$key]) ? $this->fields[$field][$key] : $default;
- }
- return $this->fields[$field];
- }
- return $default;
- }
- /**
- *
- * @param string $field
- * @param string $key attribute name
- * @param mixed $value default value if not set, default is null
- * @return e_admin_controller_ui
- */
- public function setFieldAttr($field, $key = null, $value = null)
- {
- // add field array
- if(is_array($field))
- {
- foreach ($field as $f => $atts)
- {
- $this->setFieldAttr($f, $atts);
- }
- return $this;
- }
- // remove a field
- if(null === $key)
- {
- unset($this->fields[$field]);
- return $this;
- }
- // add to attribute array of a field
- if(is_array($key))
- {
- foreach ($key as $k => $att)
- {
- $this->setFieldAttr($field, $k, $att);
- }
- return $this;
- }
- // remove attribute from field attribute set
- if(null === $value && $key != 'type')
- {
- unset($this->fields[$field][$key]);
- return $this;
- }
- // set attribute value
- $this->fields[$field][$key] = $value;
- return $this;
- }
- /**
- * Get fields stored as user preferences
- * @return array
- */
- public function getFieldPref()
- {
- return $this->fieldpref;
- }
- /**
- * Get Config data array
- * @return array
- */
- public function getPrefs()
- {
- return $this->prefs;
- }
- public function getPerPage()
- {
- return $this->perPage;
- }
-
- public function getFormQuery()
- {
- return $this->formQuery;
- }
- public function getPrimaryName()
- {
- return $this->getModel()->getFieldIdName();
- }
- public function getDefaultOrderField()
- {
- return ($this->defaultOrder ? $this->defaultOrderField : $this->getPrimaryName());
- }
- public function getDefaultOrder()
- {
- return ($this->defaultOrder ? $this->defaultOrder : 'asc');
- }
- /**
- * Get column preference array
- * @return array
- */
- public function getUserPref()
- {
- //global $user_pref;
- // return vartrue($user_pref['admin_cols_'.$this->getTableName()], array());
- return e107::getUser()->getPref('admin_cols_'.$this->getTableName(), array());
- }
- /**
- * Set column preference array
- * @return boolean success
- */
- public function setUserPref($new)
- {
- //global $user_pref;
- //e107::getUser()->getConfig()->setData($new);
- //$user_pref['admin_cols_'.$this->getTableName()] = $new;
- //$this->fieldpref = $new;
- //return save_prefs('user');
- $this->fieldpref = $new;
- return e107::getUser()->getConfig()
- ->set('admin_cols_'.$this->getTableName(), $new)
- ->save();
- }
- /**
- * Get current model
- *
- * @return e_admin_model
- */
- public function getModel()
- {
- if(null === $this->_model)
- {
- $this->_setModel();
- }
- return $this->_model;
- }
- /**
- * Set controller model
- * @param e_admin_model $model
- * @return e_admin_controller_ui
- */
- public function setModel($model)
- {
- $this->_model = $model;
- return $this;
- }
- /**
- * Get model validation array
- * @return array
- */
- public function getValidationRules()
- {
- return $this->getModel()->getValidationRules();
- }
- /**
- * Get model data field array
- * @return array
- */
- public function getDataFields()
- {
- return $this->getModel()->getDataFields();
- }
- /**
- * Get model table or alias
- * @param boolean $alias get table alias on true, default false
- * @param object $prefix add e107 special '#' prefix, default false
- * @return string
- */
- public function getTableName($alias = false, $prefix = false)
- {
- if($alias) return ($this->tableAlias ? $this->tableAlias : '');
- return ($prefix ? '#' : '').$this->getModel()->getModelTable();
- }
- public function getIfTableAlias($prefix = false, $quote = false) //XXX May no longer by useful. see joinAlias()
- {
- $alias = $this->getTableName(true);
- if($alias)
- {
- return $alias;
- }
- return ( !$quote ? $this->getTableName(false, $prefix) : '`'.$this->getTableName(false, $prefix).'`' );
- }
- /**
- * Get join table data - XXX DEPRECATE?
- * @param string $table if null all data will be returned
- * @param string $att_name search for specific attribute, default null (no search)
- * @return mixed
- */
- public function getJoinData($table = null, $att_name = null, $default_att = null)
- {
- if(null === $table)
- {
- return $this->tableJoin;
- }
- if(null === $att_name)
- {
- return (isset($this->tableJoin[$table]) ? $this->tableJoin[$table] : array());
- }
- return (isset($this->tableJoin[$table][$att_name]) ? $this->tableJoin[$table][$att_name] : $default_att);
- }
- public function setJoinData($table, $data) //XXX - DEPRECATE?
- {
- if(null === $data)
- {
- unset($this->tableJoin[$table]);
- return $this;
- }
- $this->tableJoin[$table] = (array) $data;
- return $this;
- }
- /**
- * User defined model setter
- * @return e_admin_controller_ui
- */
- protected function _setModel()
- {
- return $this;
- }
- /**
- * Get current tree model
- * @return e_admin_tree_model
- */
- public function getTreeModel()
- {
- if(null === $this->_tree_model)
- {
- $this->_setTreeModel();
- }
- return $this->_tree_model;
- }
- /**
- * Set controller tree model
- * @param e_admin_tree_model $tree_model
- * @return e_admin_controller_ui
- */
- public function setTreeModel($tree_model)
- {
- $this->_tree_model = $tree_model;
- return $this;
- }
- /**
- * Get currently parsed model while in list mode
- * Model instance is registered by e_form::renderListForm()
- *
- * @return e_admin_model
- */
- public function getListModel()
- {
- return e107::getRegistry('core/adminUI/currentListModel');
- }
- public function setListModel($model)
- {
- e107::setRegistry('core/adminUI/currentListModel', $model);
- return $this;
- }
- /**
- * User defined tree model setter
- * @return e_admin_controller_ui
- */
- protected function _setTreeModel()
- {
- return $this;
- }
- /**
- * Get extended (UI) Form instance
- *
- * @return e_admin_form_ui
- */
- public function getUI()
- {
- if(null === $this->_ui)
- {
- $this->_setUI();
- }
- return $this->_ui;
- }
- /**
- * Set controller UI form
- * @param e_admin_form_ui $ui
- * @return e_admin_controller_ui
- */
- public function setUI($ui)
- {
- $this->_ui = $ui;
- return $this;
- }
- /**
- * User defined UI form setter
- * @return e_admin_controller_ui
- */
- protected function _setUI()
- {
- return $this;
- }
- /**
- * Get Config object
- * @return e_plugin_pref or e_core_pref when used in core areas
- */
- public function getConfig()
- {
- if(null === $this->_pref)
- {
- $this->_setConfig();
- }
- return $this->_pref;
- }
- /**
- * Set Config object
- * @return e_admin_controller_ui
- */
- public function setConfig($config)
- {
- $this->_prefs = $config;
- return $this;
- }
- /**
- * User defined config setter
- * @return e_admin_controller_ui
- */
- protected function _setConfig()
- {
- return $this;
- }
- /**
- * Manage column visibility
- * @param string $batch_trigger
- * @return none
- */
- public function manageColumns()
- {
- $cols = array();
- $posted = $this->getPosted('e-columns', array());
- foreach ($this->getFields() as $field => $attr)
- {
- if((vartrue($attr['forced']) || in_array($field, $posted)) && !vartrue($attr['nolist']))
- {
- $cols[] = $field;
- continue;
- }
- }
- if($cols)
- {
- $this->setUserPref($cols);
- }
- }
- /**
- * Handle posted batch options routine
- * @param string $batch_trigger
- * @return e_admin_controller_ui
- */
- protected function _handleListBatch($batch_trigger)
- {
- $tp = e107::getParser();
- //$multi_name = vartrue($this->fields['checkboxes']['toggle'], 'multiselect');
- $multi_name = $this->getFieldAttr('checkboxes', 'toggle', 'multiselect');
- $selected = array_values($this->getPosted($multi_name, array()));
- $trigger = $tp->toDB(explode('__', $batch_trigger));
- if(empty($selected) && !$this->getPosted('etrigger_delete_confirm')) // it's a delete batch, confirm screen
- {
- $params = $this->getFieldAttr($trigger[1], 'writeParms', array());
- if(!is_array($params)) parse_str($params, $params);
- if(!vartrue($params['batchNoCheck']))
- {
- return $this;
- }
- }
-
- if($selected)
- {
- foreach ($selected as $i => $_sel)
- {
- $selected[$i] = preg_replace('/[^\w-:.]/', '', $_sel);
- }
- }
-
- $this->setTriggersEnabled(false); //disable further triggering
-
- switch($trigger[0])
- {
- case 'delete': //FIXME - confirmation screen
- //method handleListDeleteBatch(); for custom handling of 'delete' batch
- // if(empty($selected)) return $this;
- // don't check selected data - subclass need to check additional post variables(confirm screen)
- $method = 'handle'.$this->getRequest()->getActionName().'DeleteBatch';
- if(method_exists($this, $method)) // callback handling
- {
- $this->$method($selected);
- }
- break;
- case 'bool':
- if(empty($selected)) return $this;
- $field = $trigger[1];
- $value = $trigger[2] ? 1 : 0;
- //something like handleListBoolBatch(); for custom handling of 'bool' batch
- $method = 'handle'.$this->getRequest()->getActionName().'BoolBatch';
- if(method_exists($this, $method)) // callback handling
- {
- $this->$method($selected, $field, $value);
- }
- break;
- case 'boolreverse':
- if(empty($selected)) return $this;
- $field = $trigger[1];
- //something like handleListBoolreverseBatch(); for custom handling of 'boolreverse' batch
- $method = 'handle'.$this->getRequest()->getActionName().'BoolreverseBatch';
- if(method_exists($this, $method)) // callback handling
- {
- $this->$method($selected, $field);
- }
- break;
-
- // see commma, userclasses batch options
- case 'attach':
- case 'deattach':
- case 'addAll':
- case 'clearAll':
- $field = $trigger[1];
- $value = $trigger[2];
-
- if($trigger[0] == 'addAll')
- {
- $parms = $this->getFieldAttr($field, 'writeParms', array());
- if(!is_array($parms)) parse_str($parms, $parms);
- unset($parms['__options']);
- $value = $parms;
- if(empty($value)) return $this;
- if(!is_array($value)) $value = array_map('trim', explode(',', $value));
- }
-
- if(method_exists($this, 'handleCommaBatch'))
- {
- $this->handleCommaBatch($selected, $field, $value, $trigger[0]);
- }
- break;
-
- // append to userclass list
- case 'ucadd':
- case 'ucremove':
- //if(empty($selected)) return $this;
- $field = $trigger[1];
- $class = $trigger[2];
- $user = e107::getUser();
- $e_userclass = e107::getUserClass();
-
- // check userclass manager class
- if (!isset($e_userclass->class_tree[$class]) || !$user->checkClass($e_userclass->class_tree[$class]))
- {
- return $this;
- }
- if(method_exists($this, 'handleCommaBatch'))
- {
- $trigger[0] = $trigger[0] == 'ucadd' ? 'attach' : 'deattach';
- $this->handleCommaBatch($selected, $field, $class, $trigger[0]);
- }
- break;
-
- // add all to userclass list
- // clear userclass list
- case 'ucaddall':
- case 'ucdelall':
- $field = $trigger[1];
- $user = e107::getUser();
- $e_userclass = e107::getUserClass();
- $parms = $this->getFieldAttr($field, 'writeParms', array());
- if(!is_array($parms)) parse_str($parms, $parms);
- if(!vartrue($parms['classlist'])) return $this;
-
- $classes = $e_userclass->uc_required_class_list($parms['classlist']);
- foreach ($classes as $id => $label)
- {
- // check userclass manager class
- if (!isset($e_userclass->class_tree[$id]) || !$user->checkClass($e_userclass->class_tree[$id]))
- {
- // TODO lan
- $msg = $tp->lanVars("You don't have management permissions on [x]",$label);
- $this->getTreeModel()->addMessageWarning($msg);
- unset($classes[$id],$msg);
- }
- }
- $this->handleCommaBatch($selected, $field, array_keys($classes), $trigger[0] === 'ucdelall' ? 'clearAll' : 'addAll');
- break;
-
- default:
- $field = $trigger[0];
- $value = $trigger[1];
- //something like handleListUrlTypeBatch(); for custom handling of 'url_type' field name
- $method = 'handle'.$this->getRequest()->getActionName().$this->getRequest()->camelize($field).'Batch';
- if(method_exists($this, $method)) // callback handling
- {
- $this->$method($selected, $value);
- break;
- }
- //handleListBatch(); for custom handling of all field names
- if(empty($selected)) return $this;
- $method = 'handle'.$this->getRequest()->getActionName().'Batch';
- if(method_exists($this, $method))
- {
- $this->$method($selected, $field, $value);
- }
- break;
- }
- return $this;
- }
- /**
- * Handle requested filter dropdown value
- * @param string $value
- * @return array field -> value
- */
- protected function _parseFilterRequest($filter_value)
- {
- $tp = e107::getParser();
- if(!$filter_value || $filter_value === '___reset___')
- {
- return array();
- }
- $filter = $tp->toDB(explode('__', $filter_value));
- $res = array();
- switch($filter[0])
- {
- case 'bool':
- // direct query
- $res = array($filter[1], $filter[2]);
- break;
-
- case 'datestamp':
-
- $dateConvert = array(
- "hour" => "1 hour ago",
- "day" => "24 hours ago",
- "week" => "1 week ago",
- "month" => "1 month ago",
- "year" => "1 year ago"
- );
-
- $ky = $filter[2];
- $time = vartrue($dateConvert[$ky]);
- $timeStamp = strtotime($time);
-
- $res = array($filter[1], $timeStamp);
-
- break;
- default:
- //something like handleListUrlTypeFilter(); for custom handling of 'url_type' field name filters
- $method = 'handle'.$this->getRequest()->getActionName().$this->getRequest()->camelize($filter[0]).'Filter';
- if(method_exists($this, $method)) // callback handling
- {
- //return $this->$method($filter[1], $selected); selected?
- // better approach - pass all values as method arguments
- // NOTE - callbacks are allowed to return QUERY as a string, it'll be added in the WHERE clause
- $args = array_slice($filter, 1);
- e107::getMessage()->addDebug('Executing filter callback <strong>'.get_class($this).'::'.$method.'('.implode(', ', $args).')</strong>');
- return call_user_func_array(array($this, $method), $args);
- }
- else // default handling
- {
- $res = array($filter[0], $filter[1]);
- }
- break;
- }
- //print_a($res);
- //exit;
- return $res;
- }
- /**
- * Convert posted to model values after submit (based on field type)
- * @param array $data
- * @return void
- */
- protected function convertToData(&$data)
- {
- $model = new e_model($data);
-
- foreach ($this->getFields() as $key => $attributes)
- {
- $value = vartrue($attributes['dataPath']) ? $model->getData($attributes['dataPath']) : $model->get($key);
- if(null === $value)
- {
- continue;
- }
- switch($attributes['type'])
- {
-
- case 'password': //TODO more encryption options.
- if(strlen($value) < 30) // expect a non-md5 value if less than 32 chars.
- {
- $value = md5($value);
- }
-
- break;
-
-
- case 'datestamp':
- if(!is_numeric($value))
- {
- if(vartrue($attributes['writeParms']))
- {
- parse_str($attributes['writeParms'],$opt);
- }
-
- $format = $opt['type'] ? ('input'.$opt['type']) : 'inputdate';
- $value = trim($value) ? e107::getDate()->toTime($value, $format) : 0;
- }
- break;
- case 'ip': // TODO - ask Steve if this check is required
- //if(strpos($value, '.') !== FALSE)
- {
- $value = trim($value) ? e107::getIPHandler()->ipEncode($value) : '';
- }
- break;
- case 'dropdown': // TODO - ask Steve if this check is required
- case 'lanlist':
- case 'userclasses':
- case 'comma':
- if(is_array($value))
- {
- // no sanitize here - data is added to model posted stack
- // and validated & sanitized before sent to db
- //$value = array_map(array(e107::getParser(), 'toDB'), $value);
- $value = implode(',', $value);
- }
- break;
-
- case 'images':
- //XXX FIXME - entities in stored result.
- break;
-
-
- }
-
- if(vartrue($attributes['dataPath']))
- {
- $model->setData($attributes['dataPath'], $value);
- }
- else
- {
- $model->set($key, $value);
- }
- }
- $data = $model->getData();
- unset($model);
- $this->toData($data);
- }
- /**
- * User defined method for converting POSTED to MODEL data
- * @param array $data posted data
- * @param string $type current action type - edit, create, list or user defined
- * @return void
- */
- protected function toData(&$data, $type = '')
- {
- }
- /**
- * Take approproate action after successfull submit
- *
- * @param integer $id optional, needed only if redirect action is 'edit'
- * @param string $noredirect_for don't redirect if action equals to its value
- */
- protected function doAfterSubmit($id = 0, $noredirect_for = '')
- {
- if(e_AJAX_REQUEST) return;
-
- if($noredirect_for && $noredirect_for == $this->getPosted('__after_submit_action') && $noredirect_for == $this->getAction())
- {
- return;
- }
- $choice = $this->getPosted('__after_submit_action', 0);
- switch ($choice) {
- case 'create': // create
- $this->redirectAction('create', 'id');
- break;
- case 'edit': // edit
- $this->redirectAction('edit', '', 'id='.$id);
- break;
- case 'list': // list
- $this->redirectAction('list', 'id');
- break;
- default:
- $choice = explode('|', str_replace('{ID}', $id, $choice), 3);
- $this->redirectAction(preg_replace('/[^\w-:.]/', '', $choice[0]), vartrue($choice[1]), vartrue($choice[2]));
- break;
- }
- return;
- }
- /**
- * Build ajax auto-complete filter response
- * @return string response markup
- */
- protected function renderAjaxFilterResponse($listQry = '')
- {
- $debug = false;
- $srch = $this->getPosted('searchquery');
- $this->getRequest()->setQuery('searchquery', $srch); //_modifyListQry() is requiring GET String
- $ret = '<ul>';
- $ret .= '<li>'.$srch.'<span class="informal warning"> '.LAN_FILTER_LABEL_TYPED.'</span></li>'; // fix Enter - search for typed word only
- $reswords = array();
- if(trim($srch) !== '')
- {
- // Build query
- $qry = $this->_modifyListQry(false, true, 0, 20, $listQry);
- //file_put_contents(e_LOG.'uiAjaxResponseSQL.log', $qry."\n\n", FILE_APPEND);
- // Make query
- $sql = e107::getDb();
- if($qry && $sql->db_Select_gen($qry, $debug))
- {
- while ($res = $sql->db_Fetch())
- {
- $tmp1 = array();
- $tmp = array_values(preg_grep('#'.$srch.'#i', $res));
- foreach ($tmp as $w)
- {
- if($w == $srch)
- {
- array_unshift($reswords, $w); //exact match
- continue;
- }
- preg_match('#[\S]*('.$srch.')[\S]*#i', $w, $tmp1);
- if($tmp1[0]) $reswords[] = $tmp1[0];
- }
- }
- }
- // Build response
- $reswords = array_unique($reswords);
- if($reswords)
- {
- $ret .= '<li>'.implode("</li>\n\t<li>", $reswords).'</li>';
- }
- }
- $ret .= '<li><span class="informal warning"> '.LAN_FILTER_LABEL_CLEAR.' </span></li>'; // clear filter option
- $ret .= '</ul>';
- return $ret;
- }
- /**
- * Given an alias such as 'u' or 'n.news_datestamp' - will return the associated table such as 'user' or 'news'
- */
- function getTableFromAlias($alias)
- {
- if(strpos($alias,".")!==false)
- {
- list($alias,$tmp) = explode(".",$alias,2);
- }
-
- $tmp = array_flip($this->joinAlias);
- return vartrue($tmp[$alias]);
- }
- function getJoinField($field)
- {
- return vartrue($this->joinField[$field],false);
- }
- /**
- * Parses all available field data, adds internal attributes for handling join requests
- * @return e_admin_controller_ui
- */
- protected function parseAliases()
- {
- if($this->_alias_parsed) return $this; // already parsed!!!
- $this->joinAlias(); // generate Table Aliases from listQry
-
- if($this->getJoinData())
- {
- foreach ($this->getJoinData() as $table => $att)
- {
- if(strpos($table, '.') !== false)
- {
- $tmp = explode('.', $table, 2);
- $this->setJoinData($table, null);
- $att['alias'] = $tmp[0];
- $att['table'] = $tmp[1];
- $att['__tablePath'] = $att['alias'].'.';
- $att['__tableFrom'] = '`#'.$att['table'].'` AS '.$att['alias'];
- $this->setJoinData($att['alias'], $att);
- unset($tmp);
- continue;
- }
- $att['table'] = $table;
- $att['alias'] = '';
- $att['__tablePath'] = '`#'.$att['table'].'`.';
- $att['__tableFrom'] = '`#'.$att['table'].'`';
- $this->setJoinData($table, $att);
- }
- }
-
- // check for table & field aliases
- $fields = array(); // preserve order
- foreach ($this->fields as $field => $att)
- {
- // fieldAlias.fieldName // table name no longer required as it's included in listQry. (see joinAlias() )
- if(strpos($field, '.') !== false) // manually entered alias.
- {
- $tmp = explode('.', $field, 2);
- $table = $this->getTableFromAlias($tmp[0]);
- $att['table'] = $table;
- $att['alias'] = $tmp[0];
- $att['field'] = $tmp[1];
- $att['__tableField'] = $field;
- $att['__tablePath'] = $att['alias'].'.';
- $att['__tableFrom'] = "`#".$table."`.".$tmp[1];//." AS ".$att['alias'];
- $field = $att['alias'] ? $tmp[1] : $tmp[0];
- $fields[$field] = $att;
- unset($tmp);
- }
- else
- {
- $att['table'] = $this->getIfTableAlias(false);
-
- if($newField = $this->getJoinField($field)) // Auto-Detect.
- {
- $table = $this->getTableFromAlias($newField); // Auto-Detect.
- $att['table'] = $table;
- $att['alias'] = $newField;
- $att['__tableField'] = $newField;
- // $att['__tablePath'] = $newField; ????!!!!!
- $att['__tableFrom'] = "`#".$table."`.".$field;//." AS ".$newField;
- }
- elseif(isset($this->joinAlias[$this->table]) && $field !='checkboxes' && $field !='options')
- {
- $att['alias'] = $this->joinAlias[$this->table].".".$field;
- }
- else
- {
- $att['alias'] = "";
- }
- $att['field'] = $field;
- $fields[$field] = $att;
- }
- if($fields[$field]['table'] == $this->getIfTableAlias(false))
- {
- $fields[$field]['__tableField'] = $att['alias'] ? $att['alias'] : $this->getIfTableAlias(true, true).'.'.$att['field'];
- $fields[$field]['__tableFrom'] = $this->getIfTableAlias(true, true).'.'.$att['field'].($att['alias'] ? ' AS '.$att['alias'] : '');
- }
- else
- {
- // $fields[$field]['__tableField'] = $this->getJoinData($fields[$field]['table'], '__tablePath').$field;
- }
- /*
- if($fields[$field]['table'])
- {
- if($fields[$field]['table'] == $this->getIfTableAlias(false))
- {
- $fields[$field]['__tableField'] = $att['alias'] ? $att['alias'] : $this->getIfTableAlias(true, true).'.'.$att['field'];
- $fields[$field]['__tableFrom'] = $this->getIfTableAlias(true, true).'.'.$att['field'].($att['alias'] ? ' AS '.$att['alias'] : '');
- }
- else
- {
- $fields[$field]['__tableField'] = $this->getJoinData($fields[$field]['table'], '__tablePath').$field;
- }
- }
- else
- {
- $fields[$field]['__tableField'] = '`'.$this->getTableName(false, true).'`.'.$field;
- }
- */
- }
-
- $this->fields = $fields;
-
- $this->_alias_parsed = true;
- return $this;
- }
- /**
- * Intuitive LEFT JOIN Qry support. (preferred)
- * Generate array of table names and their alias - auto-detected from listQry;
- * eg. $listQry = "SELECT m.*, u.user_id,u.user_name FROM #core_media AS m LEFT JOIN #user AS u ON m.media_author = u.user_id";
- */
- protected function joinAlias()
- {
- if($this->listQry)
- {
- preg_match_all("/`?#([\w-]+)`?\s*(as|AS)\s*([\w-])/im",$this->listQry,$matches);
- $keys = array();
- foreach($matches[1] AS $k=>$v)
- {
- if(varset($matches[3][$k]))
- {
- $this->joinAlias[$v] = $matches[3][$k]; // array. eg $this->joinAlias['core_media'] = 'm';
- }
-
- $keys[] = $matches[3][$k];
- }
-
- foreach($keys as $alias)
- {
- preg_match_all("/".$alias."\.([\w]*)/i",$this->listQry,$match);
- foreach($match[1] as $k=>$m)
- {
- $this->joinField[$m] = $match[0][$k];
- }
- }
-
- }
- elseif($this->tableJoin)
- {
- foreach ($this->tableJoin as $tbl => $data)
- {
- $matches = explode('.', $tbl, 2);
- $this->joinAlias[$matches[1]] = $matches[0]; // array. eg $this->joinAlias['core_media'] = 'm';
- //'user_name'=>'u.user_name'
- if(isset($data['fields']) && $data['fields'] !== '*')
- {
- $tmp = explode(',', $data['fields']);
- foreach ($tmp as $field)
- {
- $this->joinField[$field] = $matches[0].'.'.$field;
- }
- }
- }
- }
-
- }
- // TODO - abstract, array return type, move to parent?
- protected function _modifyListQry($raw = false, $isfilter = false, $forceFrom = false, $forceTo = false, $listQry = '')
- {
- $searchQry = array();
- $filterFrom = array();
- $request = $this->getRequest();
- $tp = e107::getParser();
- $tablePath = $this->getIfTableAlias(true, true).'.';
- $tableFrom = '`'.$this->getTableName(false, true).'`'.($this->getTableName(true) ? ' AS '.$this->getTableName(true) : '');
- $tableSFieldsArr = array(); // FROM for main table
- $tableSJoinArr = array(); // FROM for join tables
- $filter = array();
- $searchQuery = $tp->toDB($request->getQuery('searchquery', ''));
- $searchFilter = $this->_parseFilterRequest($request->getQuery('filter_options', ''));
- if($searchFilter && is_array($searchFilter))
- {
-
- list($filterField, $filterValue) = $searchFilter;
-
- if($filterField && $filterValue !== '' && isset($this->fields[$filterField]))
- {
- $_type = $this->fields[$filterField]['data'];
- if($this->fields[$filterField]['type'] === 'comma') $_type = 'set';
- switch ($_type)
- {
- case 'set':
- $searchQry[] = "FIND_IN_SET('".$tp->toDB($filterValue)."',".$this->fields[$filterField]['__tableField'].")";
- break;
-
- case 'int':
- case 'integer':
- if($this->fields[$filterField]['type'] == 'datestamp') // Past Month, Past Year etc.
- {
- $searchQry[] = $this->fields[$filterField]['__tableField']." > ".intval($filterValue);
- }
- else
- {
- $searchQry[] = $this->fields[$filterField]['__tableField']." = ".intval($filterValue);
- }
- break;
-
-
-
- default:
-
- if($this->fields[$filterField]['type'] == 'method') // More flexible filtering.
- {
- $searchQry[] = $this->fields[$filterField]['__tableField']." LIKE \"%".$tp->toDB($filterValue)."%\"";
- }
- else
- {
- $searchQry[] = $this->fields[$filterField]['__tableField']." = '".$tp->toDB($filterValue)."'";
- }
-
- //exit;
- break;
- }
-
- }
- //echo 'type= '. $this->fields[$filterField]['data'];
- // print_a($this->fields[$filterField]);
- }
- elseif($searchFilter && is_string($searchFilter))
- {
-
- // filter callbacks could add to WHERE clause
- $searchQry[] = $searchFilter;
- }
- // main table should select everything
- $tableSFieldsArr[] = $tablePath.'*';
- foreach($this->getFields() as $key => $var)
- {
- // disabled or system
- if((vartrue($var['nolist']) && !vartrue($var['filter'])) || !vartrue($var['type']))
- {
- continue;
- }
- // select FROM... for main table
- if(vartrue($var['alias']) && vartrue($var['__tableField']))
- {
- $tableSFieldsArr[] = $var['__tableField'];
- }
- // filter for WHERE and FROM clauses
- $searchable_types = array('text', 'textarea', 'bbarea', 'email', 'int', 'integer', 'str', 'string'); //method? 'user',
-
- if($var['type'] == 'method' && ($var['data'] == 'string' || $var['data'] == 'str'))
- {
- $searchable_types[] = 'method';
- }
-
- if(trim($searchQuery) !== '' && in_array($var['type'], $searchable_types) && $var['__tableField'])
- {
- if($var['type'] == 'int' || $var['type'] == 'integer')
- {
- if(is_numeric($searchQuery))
- {
- $filter[] = $var['__tableField']."=".$searchQuery;
- }
- continue;
- }
- $filter[] = $var['__tableField']." LIKE '%".$searchQuery."%'";
- if($isfilter)
- {
- $filterFrom[] = $var['__tableField'];
- }
- }
- }
- if($isfilter)
- {
- if(!$filterFrom) return false;
- $tableSFields = implode(', ', $filterFrom);
- }
- else
- {
- $tableSFields = $tableSFieldsArr ? implode(', ', $tableSFieldsArr) : $tablePath.'*';
- }
- $jwhere = array();
- $joins = array();
- //file_put_contents(e_LOG.'uiAjaxResponseSFields.log', $tableSFields."\n\n", FILE_APPEND);
- //file_put_contents(e_LOG.'uiAjaxResponseFields.log', print_r($this->getFields(), true)."\n\n", FILE_APPEND);
- if($this->getJoinData())
- {
- $qry = "SELECT SQL_CALC_FOUND_ROWS ".$tableSFields;
- foreach ($this->getJoinData() as $jtable => $tparams)
- {
- // Select fields
- if(!$isfilter)
- {
- $fields = vartrue($tparams['fields']);
- if('*' === $fields)
- {
- $tableSJoinArr[] = "{$tparams['__tablePath']}*";
- }
- elseif($fields)
- {
- $tableSJoinArr[] = $fields;
- /*$fields = explode(',', $fields);
- foreach ($fields as $field)
- {
- $qry .= ", {$tparams['__tablePath']}`".trim($field).'`';
- }*/
- }
- }
- // Prepare Joins
- $joins[] = "
- ".vartrue($tparams['joinType'], 'LEFT JOIN')." {$tparams['__tableFrom']} ON ".(vartrue($tparams['leftTable']) ? $tparams['leftTable'].'.' : $tablePath)."`".vartrue($tparams['leftField'])."` = {$tparams['__tablePath']}`".vartrue($tparams['rightField'])."`".(vartrue($tparams['whereJoin']) ? ' '.$tparams['whereJoin'] : '');
- // Prepare Where
- if(vartrue($tparams['where']))
- {
- $jwhere[] = $tparams['where'];
- }
- }
-
- //From
- $qry .= $tableSJoinArr ? ', '.implode(', ', $tableSJoinArr)." FROM ".$tableFrom : " FROM ".$tableFrom;
- // Joins
- if(count($joins) > 0)
- {
- $qry .= "\n".implode("\n", $joins);
- }
- }
- else
- {
- $qry = $listQry ? $listQry : "SELECT SQL_CALC_FOUND_ROWS ".$tableSFields." FROM ".$tableFrom;
- }
- // group field - currently auto-added only if there are joins
- // TODO - groupField property
- $groupField = '';
- if($joins && $this->getPrimaryName())
- {
- $groupField = $tablePath.$this->getPrimaryName();
- }
- if($raw)
- {
- $rawData = array(
- 'joinWhere' => $jwhere,
- 'filter' => $filter,
- 'listQrySql' => $this->listQrySql,
- 'filterFrom' => $filterFrom,
- 'search' => $searchQry,
- 'tableFromName' => $tableFrom,
- );
- $rawData['tableFrom'] = $tableSFieldsArr;
- $rawData['joinsFrom'] = $tableSJoinArr;
- $rawData['joins'] = $joins;
- $rawData['groupField'] = $groupField;
- $rawData['orderField'] = isset($this->fields[$orderField]) ? $this->fields[$orderField]['__tableField'] : '';
- $rawData['orderType'] = $request->getQuery('asc') == 'desc' ? 'DESC' : 'ASC';
- $rawData['limitFrom'] = false === $forceFrom ? intval($request->getQuery('from', 0)) : intval($forceFrom);
- $rawData['limitTo'] = false === $forceTo ? intval($this->getPerPage()) : intval($forceTo);
- return $rawData;
- }
- // join where
- if(count($jwhere) > 0)
- {
- $searchQry[] = " (".implode(" AND ",$jwhere)." )";
- }
- // filter where
- if(count($filter) > 0)
- {
- $searchQry[] = " ( ".implode(" OR ",$filter)." ) ";
- }
- // more user added sql
- if(isset($this->listQrySql['db_where']) && $this->listQrySql['db_where'])
- {
- if(is_array($this->listQrySql['db_where']))
- {
- $searchQry[] = implode(" AND ", $this->listQrySql['db_where']);
- }
- else
- {
- $searchQry[] = $this->listQrySql['db_where'];
- }
- }
-
-
- // where query
- if(count($searchQry) > 0)
- {
- // add more where details on the fly via $this->listQrySql['db_where'];
- $qry .= (strripos($qry, 'where')==FALSE) ? " WHERE " : " AND "; // Allow 'where' in custom listqry
- $qry .= implode(" AND ", $searchQry);
- }
- // GROUP BY if needed
- if($groupField)
- {
- $qry .= ' GROUP BY '.$groupField;
- }
- // only when no custom order is required
- if($this->listOrder && !$request->getQuery('field') && !$request->getQuery('asc'))
- {
- $qry .= ' ORDER BY '.$this->listOrder;
- }
- elseif(false !== $this->listOrder)
- {
- $orderField = $request->getQuery('field', $this->getDefaultOrderField());
- $orderDef = (null === $request->getQuery('asc', null) ? $this->getDefaultOrder() : $request->getQuery('asc'));
- if(isset($this->fields[$orderField]) && strpos($this->listQry,'ORDER BY')==FALSE) //override ORDER using listQry (admin->sitelinks)
- {
- // no need of sanitize - it's found in field array
- $qry .= ' ORDER BY '.$this->fields[$orderField]['__tableField'].' '.(strtolower($orderDef) == 'desc' ? 'DESC' : 'ASC');
- }
- }
-
- if(isset($this->filterQry)) // custom query on filter. (see downloads plugin)
- {
- $qry = $this->filterQry;
- }
-
- if($this->getPerPage() || false !== $forceTo)
- {
- $from = false === $forceFrom ? intval($request->getQuery('from', 0)) : intval($forceFrom);
- if(false === $forceTo) $forceTo = $this->getPerPage();
- $qry .= ' LIMIT '.$from.', '.intval($forceTo);
- }
- // Debug Filter Query.
-
- // echo $qry.'<br />';
- // print_a($_GET);
- return $qry;
- }
- /**
- * Manage submit item
- * Note: $callbackBefore will break submission if returns false
- *
- * @param string $callbackBefore existing method from $this scope to be called before submit
- * @param string $callbackAfter existing method from $this scope to be called after successfull submit
- * @param string $noredirectAction passed to doAfterSubmit()
- * @return boolean
- */
- protected function _manageSubmit($callbackBefore = '', $callbackAfter = '', $callbackError = '', $noredirectAction = '')
- {
- $model = $this->getModel();
- $old_data = $model->getData();
- $_posted = $this->getPosted();
- $this->convertToData($_posted);
- if($callbackBefore && method_exists($this, $callbackBefore))
- {
- $data = $this->$callbackBefore($_posted, $old_data, $model->getId());
- if(false === $data)
- {
- // we don't wanna loose posted data
- $model->setPostedData($_posted, null, false, false);
- return false;
- }
- if($data && is_array($data))
- {
- // add to model data fields array if required
- foreach ($data as $f => $val)
- {
- if($this->getFieldAttr($f, 'data'))
- {
- $model->setDataField($f, $this->getFieldAttr($f, 'data'));
- }
- }
- $_posted = array_merge($_posted, $data);
- }
- }
- // Scenario I - use request owned POST data - toForm already executed
- $model->setPostedData($_posted, null, false, false)
- ->save(true);
- // Scenario II - inner model sanitize
- //$this->getModel()->setPosted($this->convertToData($_POST, null, false, true);
- // Take action based on use choice after success
- if(!$this->getModel()->hasError())
- {
- // callback (if any)
- if($callbackAfter && method_exists($this, $callbackAfter))
- {
- $this->$callbackAfter($model->getData(), $old_data, $model->getId());
- }
- $model->setMessages(true); //FIX - move messages (and session messages) to the default stack
- $this->doAfterSubmit($model->getId(), $noredirectAction);
- return true;
- }
- elseif($callbackError && method_exists($this, $callbackError))
- {
- // suppress messages if callback returns TRUE
- if(true !== $this->$callbackError($_posted, $old_data, $model->getId()))
- {
- // Copy model messages to the default message stack
- $model->setMessages();
- }
- return false;
- }
- // Copy model messages to the default message stack
- $model->setMessages();
- return false;
- }
- }
- class e_admin_ui extends e_admin_controller_ui
- {
- protected $fieldTypes = array();
- protected $dataFields = array();
- protected $validationRules = array();
- protected $table;
- protected $pid;
- protected $listQry;
- protected $editQry;
- /**
- * Markup to be auto-inserted before List filter
- * @var string
- */
- public $preFiliterMarkup = '';
- /**
- * Markup to be auto-inserted after List filter
- * @var string
- */
- public $postFiliterMarkup = '';
- /**
- * Markup to be auto-inserted at the top of Create form
- * @var string
- */
- public $headerCreateMarkup = '';
- /**
- * Markup to be auto-inserted at the bottom of Create form
- * @var string
- */
- public $footerCreateMarkup = '';
- /**
- * Markup to be auto-inserted at the top of Update form
- * @var string
- */
- public $headerUpdateMarkup = '';
- /**
- * Markup to be auto-inserted at the bottom of Update form
- * @var string
- */
- public $footerUpdateMarkup = '';
- /**
- * Show confirm screen before (batch/single) delete
- * @var boolean
- */
- public $deleteConfirmScreen = false;
-
- /**
- * Confirm screen custom message
- * @var string
- */
- public $deleteConfirmMessage = null;
- /**
- * Constructor
- * @param e_admin_request $request
- * @param e_admin_response $response
- * @param array $params [optional]
- */
- public function __construct($request, $response, $params = array())
- {
- $this->setDefaultAction($request->getDefaultAction());
- $params['enable_triggers'] = true; // override
- parent::__construct($request, $response, $params);
- if(!$this->pluginName)
- {
- $this->pluginName = 'core';
- }
- $ufieldpref = $this->getUserPref();
- if($ufieldpref)
- {
- $this->fieldpref = $ufieldpref;
- }
- $this->addTitle($this->pluginTitle, true)->parseAliases();
- }
- /**
- * Catch fieldpref submit
- * @return none
- */
- public function ListEcolumnsTrigger()
- {
- $this->setTriggersEnabled(false); //disable further triggering
- parent::manageColumns();
- }
- /**
- * Catch batch submit
- * @param string $batch_trigger
- * @return none
- */
- public function ListBatchTrigger($batch_trigger)
- {
- $this->setPosted('etrigger_batch', null);
- if($this->getPosted('etrigger_cancel'))
- {
- $this->setPosted(array());
- return; // always break on cancel!
- }
- $this->deleteConfirmScreen = true; // Confirm screen ALWAYS enabled when multi-deleting!
- // proceed ONLY if there is no other trigger, except delete confirmation
- if($batch_trigger && !$this->hasTrigger(array('etrigger_delete_confirm'))) $this->_handleListBatch($batch_trigger);
- }
- /**
- * Batch delete trigger
- * @param array $selected
- * @return void
- */
- protected function handleListDeleteBatch($selected)
- {
-
- $tp = e107::getParser();
-
- if(!$this->getBatchDelete())
- {
- e107::getMessage()->add(LAN_UI_BATCHDEL_ERROR, E_MESSAGE_WARNING);
- return;
- }
- if($this->deleteConfirmScreen)
- {
- if(!$this->getPosted('etrigger_delete_confirm'))
- {
- // ListPage will show up confirmation screen
- $this->setPosted('delete_confirm_value', implode(',', $selected));
- return;
- }
- else
- {
- // already confirmed, resurrect selected values
- $selected = explode(',', $this->getPosted('delete_confirm_value'));
- foreach ($selected as $i => $_sel)
- {
- $selected[$i] = preg_replace('/[^\w-:.]/', '', $_sel);
- }
- }
- }
- // delete one by one - more control, less performance
- // pass afterDelete() callback to tree delete method
- $set_messages = true;
- $delcount = 0;
- $nfcount = 0;
- foreach ($selected as $id)
- {
- $data = array();
- $model = $this->getTreeModel()->getNode($id);
- if($model)
- {
- $data = $model->getData();
- if($this->beforeDelete($data, $id))
- {
- $check = $this->getTreeModel()->delete($id);
- if($check) $delcount++;
- if(!$this->afterDelete($data, $id, $check))
- {
- $set_messages = false;
- }
- }
- }
- else
- {
- $set_messages = true;
- $nfcount++;
- }
- }
- //$this->getTreeModel()->delete($selected);
- if($set_messages)
- {
- $this->getTreeModel()->setMessages();
- // FIXME lan
- if($delcount) e107::getMessage()->addSuccess($tp->lanVars('[x] record(s) successfully deleted.', $delcount, true));
- if($nfcount) e107::getMessage()->addError($tp->lanVars('[x] records not found and not deleted.', $nfcount,true));
- }
- //$this->redirect();
- }
- /** TODO
- * Batch copy trigger
- * @param array $selected
- * @return void
- */
- protected function handleListCopyBatch($selected)
- {
- // Batch Copy
- $res = $this->getTreeModel()->copy($selected);
- // callback
- $this->afterCopy($res, $selected);
- // move messages to default stack
- $this->getTreeModel()->setMessages();
- // send messages to session
- e107::getMessage()->moveToSession();
- // redirect
- $this->redirect();
- }
- /**
- * Batch URL trigger
- * @param array $selected
- * @return void
- */
- protected function handleListUrlBatch($selected)
- {
- if($this->_add2nav($selected))
- {
- e107::getMessage()->moveToSession();
- $this->redirect();
- }
- }
- /** TODO
- * Batch Featurebox Transfer
- * @param array $selected
- * @return void
- */
- protected function handleListFeatureboxBatch($selected)
- {
- if($this->_add2featurebox($selected))
- {
- e107::getMessage()->moveToSession();
- $this->redirect();
- }
- }
-
- protected function _add2nav($selected)
- {
- if(empty($selected)) return false;// TODO warning message
-
- if(!is_array($selected)) $selected = array($selected);
- $sql = e107::getDb();
- $urlData = $this->getUrl();
- $allData = $this->getTreeModel()->url($selected, array('sc' => true), true);
- e107::getMessage()->addDebug('Using Url Route:'.$urlData['route']);
-
- $scount = 0;
- foreach($allData as $id => $data)
- {
- $name = $data['name'];
- $desc = $data['description'];
-
- $link = $data['url'];
-
- $link = str_replace('{e_BASE}', "", $link); // TODO temporary here, discuss
-
- // _FIELD_TYPES auto created inside mysql handler now
- $linkArray = array(
- 'link_name' => $name,
- 'link_url' => $link,
- 'link_description' => e107::getParser()->toDB($desc), // retrieved field type is string, we might need todb here
- 'link_button' => '',
- 'link_category' => 255, // Using an unassigned template rather than inactive link-class, since other inactive links may already exist.
- 'link_order' => 0,
- 'link_parent' => 0,
- 'link_open' => '',
- 'link_class' => 0,
- 'link_sefurl' => e107::getParser()->toDB($urlData['route'].'?'.$id),
- );
-
- $res = $sql->insert('links', $linkArray);
-
- // FIXME lans
- if($res !== FALSE)
- {
- e107::getMessage()->addSuccess('Created Sitelink: <b>'.($name ? $name : 'n/a')."</b>");
- $scount++;
- }
- else
- {
- if($sql->getLastErrorNumber())
- {
- e107::getMessage()->addError('SQL Link Creation Error'); //TODO - Lan
- e107::getMessage()->addDebug('SQL Link Creation Error #'.$sql->getLastErrorNumber().': '.$sql->getLastErrorText());
- }
- else
- {
- e107::getMessage()->addError('Unknown error: <b>'.$name."</b> not added");
- }
- }
-
- }
-
- if($scount > 0)
- {
- e107::getMessage()->addSuccess("<br /><strong>{$scount}</strong> new sitelinks were added but are currently unassigned. You should now modify these links to your liking.<br /><br /><a class='btn btn-small btn-primary' href='".e_ADMIN_ABS."links.php?searchquery=&filter_options=link_category__255'>Modify Links</a>");
- return $scount;
- }
-
- return false;
-
- }
- protected function _add2featurebox($selected)
- {
- // FIX - don't allow if plugin not installed
- if(!e107::isInstalled('featurebox'))
- {
- return false;
- }
-
- if(empty($selected)) return false;// TODO warning message
-
- if(!is_array($selected)) $selected = array($selected);
- $sql = e107::getDb();
- $tree = $this->getTreeModel();
- $urlData = $this->getTreeModel()->url($selected, array('sc' => true), false);
- $data = $this->featurebox;
-
- $scount = 0;
- foreach($selected as $id)
- {
- if(!$tree->hasNode($id))
- {
- e107::getMessage()->addError('Item #ID '.htmlspecialchars($id).' not found.');
- continue; // TODO message
- }
-
- $model = $tree->getNode($id);
- if($data['url'] === true)
- {
- $url = $urlData[$id];
- }
- else $url = $model->get($data['url']);
- $name = $model->get($data['name']);
-
- $category = e107::getDb()->retrieve('featurebox_category', 'fb_category_id', "fb_category_template='unassigned'");
-
- $fbArray = array (
- 'fb_title' => $name,
- 'fb_text' => $model->get($data['description']),
- 'fb_image' => vartrue($data['image']) ? $model->get($data['image']) : '',
- 'fb_imageurl' => $url,
- 'fb_class' => isset($data['visibility']) && $data['visibility'] !== false ? $model->get($data['visibility']) : e_UC_ADMIN,
- 'fb_template' => 'default',
- 'fb_category' => $category, // TODO popup - choose category
- 'fb_order' => $scount,
- );
- $res = $sql->insert('featurebox', $fbArray);
- // FIXME lans
- if($res !== FALSE)
- {
- e107::getMessage()->addSuccess('Created Featurebox Item: <b>'.($name ? $name : 'n/a')."</b>");
- $scount++;
- }
- else
- {
- if($sql->getLastErrorNumber())
- {
- e107::getMessage()->addError('SQL Featurebox Creation Error'); //TODO - Lan
- e107::getMessage()->addDebug('SQL Featurebox Creation Error #'.$sql->getLastErrorNumber().': '.$sql->getLastErrorText());
- }
- else
- {
- e107::getMessage()->addError('Unknown error: <b>'.$name."</b> not added");
- }
- }
-
- }
-
- if($scount > 0)
- {
- e107::getMessage()->addSuccess("<br /><strong>{$scount}</strong> new featurebox items were added but are currently unassigned. You should now modify these items to your liking.<br /><br /><a class='btn btn-small btn-primary' href='".e_PLUGIN_ABS."featurebox/admin_config.php?searchquery=&filter_options=fb_category__{$category}'>Modify Featurebox Items</a>");
- return $scount;
- }
-
- return false;
-
- }
-
- /**
- * Batch boolean trigger
- * @param array $selected
- * @return void
- */
- protected function handleListBoolBatch($selected, $field, $value)
- {
- $cnt = $this->getTreeModel()->update($field, $value, $selected, $value, false);
- if($cnt)
- {
- $caption = e107::getParser()->lanVars(LAN_UI_BATCH_BOOL_SUCCESS, $cnt, true);
- $this->getTreeModel()->addMessageSuccess($caption);
- }
- $this->getTreeModel()->setMessages();
- }
- /**
- * Batch boolean reverse trigger
- * @param array $selected
- * @return void
- */
- protected function handleListBoolreverseBatch($selected, $field, $value)
- {
- $tree = $this->getTreeModel();
- $cnt = $tree->update($field, "1-{$field}", $selected, null, false);
- if($cnt)
- {
- $caption = e107::getParser()->lanVars(LAN_UI_BATCH_REVERSED_SUCCESS, $cnt, true);
- $tree->addMessageSuccess($caption);
- //sync models
- $tree->load(true);
- }
- $this->getTreeModel()->setMessages();
- }
- public function handleCommaBatch($selected, $field, $value, $type)
- {
- $tree = $this->getTreeModel();
- $cnt = $rcnt = 0;
- $value = e107::getParser()->toDb($value);
-
- switch ($type)
- {
- case 'attach':
- case 'deattach':
- $this->_setModel();
- foreach ($selected as $key => $id)
- {
- $node = $tree->getNode($id);
- if(!$node) continue;
- $val = $node->get($field);
-
- if(empty($val)) $val = array();
- elseif(!is_array($val)) $val = explode(',', $val);
-
- if($type === 'deattach')
- {
- $search = array_search($value, $val);
- if(false === $search) continue;
- unset($val[$search]);
- sort($val);
- $val = implode(',', $val);
- $node->set($field, $val);
- $check = $this->getModel()->setData($node->getData())->save(false, true);
-
- if(false === $check) $this->getModel()->setMessages();
- else $rcnt++;
- continue;
- }
-
- // attach it
- if(false === in_array($value, $val))
- {
- $val[] = $value;
- sort($val);
- $val = implode(',', array_unique($val));
- $node->set($field, $val);
- $check = $this->getModel()->setData($node->getData())->save(false, true);
- if(false === $check) $this->getModel()->setMessages();
- else $cnt++;
- }
- }
- $this->_model = null;
- break;
-
- case 'addAll':
- if(!empty($value))
- {
- if(is_array($value))
- {
- sort($value);
- $value = implode(',', array_map('trim', $value));
- }
-
- $cnt = $this->getTreeModel()->update($field, $value, $selected, true, true);
- }
- else
- {
- // TODO lan
- $this->getTreeModel()->addMessageWarning("Comma list is empty, aborting.")->setMessages();
- }
- break;
-
- case 'clearAll':
- $allowed = !is_array($value) ? explode(',', $value) : $value;
- if(!$allowed)
- {
- $rcnt = $this->getTreeModel()->update($field, '', $selected, '', true);
- }
- else
- {
- $this->_setModel();
- foreach ($selected as $key => $id)
- {
- $node = $tree->getNode($id);
- if(!$node) continue;
-
- $val = $node->get($field);
-
- // nothing to do
- if(empty($val)) break;
- elseif(!is_array($val)) $val = explode(',', $val);
-
- // remove only allowed, see userclass
- foreach ($val as $_k => $_v)
- {
- if(in_array($_v, $allowed))
- {
- unset($val[$_k]);
- }
- }
-
- sort($val);
- $val = !empty($val) ? implode(',', $val) : '';
- $node->set($field, $val);
- $check = $this->getModel()->setData($node->getData())->save(false, true);
-
- if(false === $check) $this->getModel()->setMessages();
- else $rcnt++;
- }
- $this->_model = null;
- }
- // format for proper message
- $value = implode(',', $allowed);
- break;
- }
- if($cnt)
- {
- $vttl = $this->getUI()->renderValue($field, $value, $this->getFieldAttr($field));
- $caption = e107::getParser()->lanVars(LAN_UI_BATCH_UPDATE_SUCCESS, array('x'=>$vttl, 'y'=>$cnt), true);
- $this->getTreeModel()->addMessageSuccess($caption);
- }
- elseif($rcnt)
- {
- $vttl = $this->getUI()->renderValue($field, $value, $this->getFieldAttr($field));
- $caption = e107::getParser()->lanVars(LAN_UI_BATCH_DEATTACH_SUCCESS, array('x'=>$vttl, 'y'=>$cnt), true);
- $this->getTreeModel()->addMessageSuccess($caption);
- }
- $this->getTreeModel()->setMessages();
- }
- /**
- * Batch default (field) trigger
- * @param array $selected
- * @return void
- */
- protected function handleListBatch($selected, $field, $value)
- {
- // special exceptions
-
- if($value == '#delete') // see admin->users
- {
- $val = "''";
- $value = "(empty)";
- }
- elseif($value == "#null")
- {
- $val = null;
- $value = "(empty)";
- }
- else
- {
- $val = "'".$value."'";
- }
-
- if($field == 'options') // reserved field type. see: admin -> media-manager - batch rotate image.
- {
- return;
- }
-
- $cnt = $this->getTreeModel()->update($field, $val, $selected, true, false);
- if($cnt)
- {
- $vttl = $this->getUI()->renderValue($field, $value, $this->getFieldAttr($field));
- $msg = e107::getParser()->lanVars(LAN_UI_BATCH_UPDATE_SUCCESS, array('x' => $vttl, 'y' => $cnt), true);
- $this->getTreeModel()->addMessageSuccess($msg);
- // force reload the collection from DB, fix some issues as 'observer' is executed before the batch handler
- $this->getTreeModel()->setParam('db_query', $this->_modifyListQry(false, false, false, false, $this->listQry))->load(true);
- }
- $this->getTreeModel()->setMessages();
- return $cnt;
- }
- /**
- * Catch delete submit
- * @param string $batch_trigger
- * @return none
- */
- public function ListDeleteTrigger($posted)
- {
- if($this->getPosted('etrigger_cancel'))
- {
- $this->setPosted(array());
- return; // always break on cancel!
- }
- $id = intval(key($posted));
- if($this->deleteConfirmScreen && !$this->getPosted('etrigger_delete_confirm'))
- {
- // forward data to delete confirm screen
- $this->setPosted('delete_confirm_value', $id);
- return; // User confirmation expected
- }
- $this->setTriggersEnabled(false);
- $data = array();
- $model = $this->getTreeModel()->getNode($id); //FIXME - this has issues with being on a page other than the 1st.
- if($model)
- {
- $data = $model->getData();
- if($this->beforeDelete($data, $id))
- {
- $check = $this->getTreeModel()->delete($id);
- if($this->afterDelete($data, $id, $check))
- {
- $this->getTreeModel()->setMessages();
- }
- }
- else
- {
- $this->getTreeModel()->setMessages();// errors
- }
- }
- else //FIXME - this is a fall-back for the BUG which causes model to fail on all list pages other than the 1st
- {
- //echo "Couldn't get Node for ID: ".$id;
- // exit;
- $check = $this->getTreeModel()->delete($id);
- return;
- }
- }
- /**
- * User defined pre-delete logic
- */
- public function beforeDelete($data, $id)
- {
- return true;
- }
- /**
- * User defined after-delete logic
- */
- public function afterDelete($deleted_data, $id, $deleted_check)
- {
- return true;
- }
- /**
- * List action header
- * @return void
- */
- public function ListHeader()
- {
- //e107::js('core','core/tabs.js','prototype');
- //e107::js('core','core/admin.js','prototype');
- }
- /**
- * List action observer
- * @return void
- */
- public function ListObserver()
- {
- $this->getTreeModel()->setParam('db_query', $this->_modifyListQry(false, false, false, false, $this->listQry))->load();
- $this->addTitle();
- }
- /**
- * Filter response ajax page
- * @return string
- */
- public function FilterAjaxPage()
- {
- return $this->renderAjaxFilterResponse($this->listQry); //listQry will be used only if available
- }
-
- /**
- * Inline edit action
- * @return void
- */
- public function InlineAjaxPage()
- {
- $this->logajax('Field not found');
- $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
- if(!vartrue($_POST['name']) || !vartrue($this->fields[$_POST['name']]))
- {
- header($protocol.': 404 Not Found', true, 404);
- header("Status: 404 Not Found", true, 404);
- echo 'Field not found'; // FIXME lan
- $this->logajax('Field not found');
- return;
- }
-
- $_name = $_POST['name'];
- $_value = $_POST['value'];
- $parms = $this->fields[$_name]['readParms'] ? $this->fields[$_name]['readParms'] : '';
- if(!is_array($parms)) parse_str($parms, $parms);
- if(vartrue($parms['editable'])) $this->fields[$_name]['inline'] = true;
-
- if(vartrue($this->fields[$_name]['noedit']) || vartrue($this->fields[$_name]['nolist']) || !vartrue($this->fields[$_name]['inline']))
- {
- header($protocol.': 403 Forbidden', true, 403);
- header("Status: 403 Forbidden", true, 403);
- echo 'Forbidden'; // FIXME lan
- $this->logajax("Forbidden");
- return;
- }
-
- $this->logajax("OK?");
-
- $model = $this->getModel()->load($this->getId());
- $_POST = array(); //reset post
- $_POST[$_name] = $_value; // set current field only
-
- // generic handler - same as regular edit form submit
- $this->convertToData($_POST);
- $model->setPostedData($_POST, null, false, false)
- ->setParam('validateAvailable', true) // new param to control validate of available data only, reset on validate event
- ->update(true);
- //$res = $this->_manageSubmit('beforeUpdate', 'afterUpdate', 'onUpdateError', 'edit');
-
- if($model->hasError())
- {
- // using 400
- header($protocol.': 400 Bad Request', true, 400);
- header("Status: 400 Bad Request", true, 400);
- $this->logajax("Bad Request");
- // DEBUG e107::getMessage()->addError('Error test.', $model->getMessageStackName())->addError('Another error test.', $model->getMessageStackName());
-
- if(E107_DEBUG_LEVEL) $message = e107::getMessage()->get('debug', $model->getMessageStackName(), true);
- else $message = e107::getMessage()->get('error', $model->getMessageStackName(), true);
-
- if(!empty($message)) echo implode(' ', $message);
- return;
- }
- }
- // Temporary - but useful. :-)
- public function logajax($message)
- {
- return;
-
- $message = date('r')."\n".$message."\n";
- $message .= print_r($_POST,true);
- $message .= print_r($_GET,true);
- $message .= "---------------";
-
- file_put_contents(e_LOG.'uiAjaxResponseInline.log', $message."\n\n", FILE_APPEND);
- }
-
-
- /**
- * Drag-n-Drop sort action
- * @return void
- */
- public function SortAjaxPage()
- {
- if(!isset($_POST['all']) || empty($_POST['all']))
- {
- return;
- }
- if(!$this->sortField)
- {
- echo 'Missing sort field value';
- return;
- }
-
- $sql = e107::getDb();
- $c = ($_GET['from']) ? intval($_GET['from']) : 0;
- $updated = array();
- $step = $this->orderStep ? intval($this->orderStep) : 1;
-
- foreach($_POST['all'] as $row)
- {
-
- list($tmp,$id) = explode("-", $row, 2);
- $id = preg_replace('/[^\w-:.]/', '', $id);
- if(!is_numeric($id)) $id = "'{$id}'";
- if($sql->db_Update($this->table, $this->sortField." = {$c} WHERE ".$this->pid." = ".$id))
- {
- $updated[] = $id;
- }
- // echo($sql->getLastQuery()."\n");
- $c += $step;
- }
- //echo "Updated ".implode(",",$updated);
- }
- /**
- * Generic List action page
- * @return string
- */
- public function ListPage()
- {
- if($this->deleteConfirmScreen && !$this->getPosted('etrigger_delete_confirm') && $this->getPosted('delete_confirm_value'))
- {
- // 'edelete_confirm_data' set by single/batch delete trigger
- return $this->getUI()->getConfirmDelete($this->getPosted('delete_confirm_value')); // User confirmation expected
- }
- return $this->getUI()->getList();
- }
- /**
- * List action observer
- * @return void
- */
- public function ListAjaxObserver()
- {
- $this->getTreeModel()->setParam('db_query', $this->_modifyListQry(false, false, 0, false, $this->listQry))->load();
- }
- /**
- * Generic List action page (Ajax)
- * @return string
- */
- public function ListAjaxPage()
- {
- return $this->getUI()->getList(true);
- }
- /**
- * Generic Edit observer
- */
- public function EditObserver()
- {
- $this->getModel()->load($this->getId());
- $this->addTitle();
- }
- /**
- * Generic Create submit trigger
- */
- public function EditCancelTrigger()
- {
- $this->redirectAction('list', 'id');
- }
- /**
- * Generic Edit submit trigger
- */
- public function EditSubmitTrigger()
- {
- $this->_manageSubmit('beforeUpdate', 'afterUpdate', 'onUpdateError', 'edit');
- }
- /**
- * Edit - send JS to page Header
- * @return none
- */
- function EditHeader()
- {
- // e107::getJs()->requireCoreLib('core/admin.js');
- e107::js('core','core/admin.js','prototype');
- }
- /**
- * Generic Edit page
- * @return string
- */
- public function EditPage()
- {
- return $this->CreatePage();
- }
- /**
- * Generic Create observer
- * @return string
- */
- public function CreateObserver()
- {
- $this->setTriggersEnabled(true);
- $this->addTitle();
- }
- /**
- * Generic Create submit trigger
- */
- public function CreateCancelTrigger()
- {
- $this->redirectAction('list', 'id');
- }
- /**
- * Generic Create submit trigger
- */
- public function CreateSubmitTrigger()
- {
- $this->_manageSubmit('beforeCreate', 'afterCreate', 'onCreateError');
- }
- /**
- * User defined pre-create logic, return false to prevent DB query execution
- * @param $new_data
- * @param $old_data
- */
- public function beforeCreate($new_data, $old_data)
- {
- }
- /**
- * User defined after-create logic
- * @param $new_data
- * @param $old_data
- * @param $id
- */
- public function afterCreate($new_data, $old_data, $id)
- {
- }
- /**
- * User defined error handling, return true to suppress model messages
- * @param $new_data
- * @param $old_data
- */
- public function onCreateError($new_data, $old_data)
- {
- }
- /**
- * User defined pre-update logic, return false to prevent DB query execution
- * @param $new_data
- * @param $old_data
- */
- public function beforeUpdate($new_data, $old_data, $id)
- {
- }
- /**
- * User defined after-update logic
- * @param $new_data
- * @param $old_data
- */
- public function afterUpdate($new_data, $old_data, $id)
- {
- }
- /**
- * User defined error handling, return true to suppress model messages
- */
- public function onUpdateError($new_data, $old_data, $id)
- {
- }
- /**
- * User defined after-update logic
- * @param mixed $result
- * @param array $selected
- * @return void
- */
- public function afterCopy($result, $selected)
- {
- }
- /**
- * Create - send JS to page Header
- * @return none
- */
- function CreateHeader()
- {
- // TODO - invoke it on className (not all textarea elements)
- //e107::getJs()->requireCoreLib('core/admin.js');
- e107::js('core','core/admin.js','prototype');
- }
- /**
- *
- * @return TBD
- */
- public function CreatePage()
- {
- return $this->getUI()->getCreate();
- }
- public function PrefsSaveTrigger()
- {
- $this->getConfig()
- ->setPostedData($this->getPosted(), null, false, false)
- //->setPosted('not_existing_pref_test', 1)
- ->save(true);
- $this->getConfig()->setMessages();
- }
-
- public function PrefsObserver()
- {
- $this->addTitle();
- }
- public function PrefsPage()
- {
- return $this->getUI()->getSettings();
- }
- /**
- * Parent overload
- * @return e_admin_ui
- */
- protected function parseAliases()
- {
- // parse table
- if(strpos($this->table, '.') !== false)
- {
- $tmp = explode('.', $this->table, 2);
- $this->table = $tmp[1];
- $this->tableAlias = $tmp[0];
- unset($tmp);
- }
- parent::parseAliases();
- return $this;
- }
- public function getPrimaryName()
- {
- // Option for working with tables having no PID
- if(!varset($this->pid) && vartrue($this->fields) && false !== $this->pid)
- {
- $message = e107::getParser()->toHtml(LAN_UI_NOPID_ERROR,true);
- e107::getMessage()->add($message, E_MESSAGE_WARNING);
- }
- return $this->pid;
- }
- public function getTableName($alias = false, $prefix = false)
- {
- if($alias) return ($this->tableAlias ? $this->tableAlias : '');
- return ($prefix ? '#' : '').$this->table;
- }
- /**
- * Validation rules retrieved from controller object
- * @return array
- */
- public function getValidationRules()
- {
- return $this->validationRules;
- }
- /**
- * Data Field array retrieved from controller object
- * @return array
- */
- public function getDataFields()
- {
- return $this->dataFields;
- }
- /**
- * Set read and write parms with drop-down-list array data (ie. type='dropdown')
- * @param str $field
- * @param array $array [optional]
- * @return none
- */
- public function setDropDown($field,$array) //TODO Have Miro check this.
- {
- $this->fields[$field]['readParms'] = $array;
- $this->fields[$field]['writeParms'] = $array;
- }
- /**
- * Set Config object
- * @return e_admin_ui
- */
- protected function _setConfig()
- {
- $this->_pref = $this->pluginName == 'core' ? e107::getConfig() : e107::getPlugConfig($this->pluginName);
- $dataFields = $validateRules = array();
- foreach ($this->prefs as $key => $att)
- {
- // create dataFields array
- $dataFields[$key] = vartrue($att['data'], 'string');
- // create validation array
- if(vartrue($att['validate']))
- {
- $validateRules[$key] = array((true === $att['validate'] ? 'required' : $att['validate']), varset($att['rule']), $att['title'], varset($att['error'], $att['help']));
- }
- /* Not implemented in e_model yet
- elseif(vartrue($att['check']))
- {
- $validateRules[$key] = array($att['check'], varset($att['rule']), $att['title'], varset($att['error'], $att['help']));
- }*/
- }
- $this->_pref->setDataFields($dataFields)->setValidationRules($validateRules);
- return $this;
- }
- /**
- * Set current model
- *
- * @return e_admin_ui
- */
- public function _setModel()
- {
- // try to create dataFields array if missing
- if(!$this->dataFields)
- {
- $this->dataFields = array();
- foreach ($this->fields as $key => $att)
- {
- if($att['type'] == 'comma' && (!vartrue($att['data']) || !vartrue($att['rule'])))
- {
- $att['data'] = 'set';
- $att['validate'] = 'set';
- $_parms = vartrue($att['writeParms'], array());
- if(is_string($_parms)) parse_str($_parms, $_parms);
- unset($_parms['__options']);
- $att['rule'] = $_parms;
- unset($_parms);
- }
- if(($key !== 'options' && false !== varset($att['data']) && null !== $att['type'] && !vartrue($att['noedit'])) || vartrue($att['forceSave']))
- {
- $this->dataFields[$key] = vartrue($att['data'], 'str');
- }
- }
- }
- // TODO - do it in one loop, or better - separate method(s) -> convertFields(validate), convertFields(data),...
- if(!$this->validationRules)
- {
- $this->validationRules = array();
- foreach ($this->fields as $key => $att)
- {
- if(null === $att['type'] || vartrue($att['noedit']))
- {
- continue;
- }
- if(vartrue($att['validate']))
- {
- $this->validationRules[$key] = array((true === $att['validate'] ? 'required' : $att['validate']), varset($att['rule']), $att['title'], varset($att['error'], vartrue($att['help'])));
- }
- /*elseif(vartrue($att['check'])) could go?
- {
- $this->checkRules[$key] = array($att['check'], varset($att['rule']), $att['title'], varset($att['error'], $att['help']));
- }*/
- }
- }
- // don't touch it if already exists
- if($this->_model) return $this;
- // default model
- $this->_model = new e_admin_model();
- $this->_model->setModelTable($this->table)
- ->setFieldIdName($this->pid)
- ->setUrl($this->url)
- ->setValidationRules($this->validationRules)
- ->setDbTypes($this->fieldTypes)
- ->setDataFields($this->dataFields)
- ->setMessageStackName('admin_ui_model_'.$this->table)
- ->setParam('db_query', $this->editQry);
- return $this;
- }
- /**
- * Set current tree
- * @return e_admin_ui
- */
- public function _setTreeModel()
- {
- // default tree model
- $this->_tree_model = new e_admin_tree_model();
- $this->_tree_model->setModelTable($this->table)
- ->setFieldIdName($this->pid)
- ->setUrl($this->url)
- ->setMessageStackName('admin_ui_tree_'.$this->table)
- ->setParams(array('model_class' => 'e_admin_model', 'model_message_stack' => 'admin_ui_model_'.$this->table ,'db_query' => $this->listQry));
- return $this;
- }
- /**
- * Get extended (UI) Form instance
- *
- * @return e_admin_ui
- */
- public function _setUI()
- {
- if($this->getParam('ui'))
- {
- $this->_ui = $this->getParam('ui');
- $this->setParam('ui', null);
- }
- else// default ui
- {
- $this->_ui = new e_admin_form_ui($this);
- }
- return $this;
- }
- }
- class e_admin_form_ui extends e_form
- {
- /**
- * @var e_admin_ui
- */
- protected $_controller = null;
- /**
- * Constructor
- * @param e_admin_ui $controller
- * @param boolean $tabindex [optional] enable form element auto tab-indexing
- */
- function __construct($controller, $tabindex = false)
- {
- $this->_controller = $controller;
- parent::__construct($tabindex);
- // protect current methods from conflict.
- $this->preventConflict();
- // user constructor
- $this->init();
- }
- protected function preventConflict()
- {
- $err = false;
- $fields = $this->getController()->getFields();
- foreach($fields as $field => $foptions)
- {
- // check form custom methods
- if(vartrue($foptions['type']) === 'method' && method_exists('e_form', $field)) // check even if type is not method. - just in case of an upgrade later by 3rd-party.
- {
- $message = e107::getParser()->lanVars(LAN_UI_FORM_METHOD_ERROR, array('x'=>$field), true);
- e107::getMessage()->addError($message);
- $err = true;
- }
- }
- /*if($err)
- {
- //echo $err;
- //exit;
- }*/
- }
- /**
- * User defined init
- */
- public function init()
- {
- }
- /**
- * TODO - lans
- * Generic DB Record Creation Form.
- * @return string
- */
- function getCreate()
- {
- $controller = $this->getController();
- $request = $controller->getRequest();
- if($controller->getId())
- {
- $legend = e107::getParser()->lanVars(LAN_UI_EDIT_LABEL, $controller->getId()); // sprintXXX(LAN_UI_EDIT_LABEL, $controller->getId());
- $form_start = vartrue($controller->headerUpdateMarkup);
- $form_end = vartrue($controller->footerUpdateMarkup);
- }
- else
- {
- $legend = LAN_UI_CREATE_LABEL;
- $form_start = vartrue($controller->headerCreateMarkup);
- $form_end = vartrue($controller->footerCreateMarkup);
- }
- $forms = $models = array();
- $forms[] = array(
- 'id' => $this->getElementId(),
-
- //'url' => e_SELF,
- //'query' => 'self', or custom GET query, self is default
- 'fieldsets' => array(
- 'create' => array(
- 'tabs' => $controller->getTabs(), //used within a single form.
- 'legend' => $legend,
- 'fields' => $controller->getFields(), //see e_admin_ui::$fields
- 'header' => $form_start,
- 'footer' => $form_end,
- 'after_submit_options' => true, // or true for default redirect options
- 'after_submit_default' => $request->getPosted('__after_submit_action', $controller->getDefaultAction()), // or true for default redirect options
- 'triggers' => 'auto', // standard create/update-cancel triggers
- )
- )
- );
- $models[] = $controller->getModel();
- return $this->renderCreateForm($forms, $models, e_AJAX_REQUEST);
- }
- /**
- * TODO - lans
- * Generic Settings Form.
- * @return string
- */
- function getSettings()
- {
- $controller = $this->getController();
- $request = $controller->getRequest();
- $legend = LAN_UI_PREF_LABEL;
- $forms = $models = array();
- $forms[] = array(
- 'id' => $this->getElementId(),
- //'url' => e_SELF,
- //'query' => 'self', or custom GET query, self is default
- 'tabs' => false, // TODO - NOT IMPLEMENTED YET - enable tabs (only if fieldset count is > 1)
- 'fieldsets' => array(
- 'settings' => array(
- 'tabs' => $controller->getPrefTabs(), //used within a single form.
- 'legend' => $legend,
- 'fields' => $controller->getPrefs(), //see e_admin_ui::$prefs
- 'after_submit_options' => false,
- 'after_submit_default' => false, // or true for default redirect options
- 'triggers' => array('save' => array(LAN_SAVE, 'update')), // standard create/update-cancel triggers
- )
- )
- );
- $models[] = $controller->getConfig();
- return $this->renderCreateForm($forms, $models, e_AJAX_REQUEST);
- }
- /**
- * Create list view
- * Search for the following GET variables:
- * - from: integer, current page
- *
- * @return string
- */
- public function getList($ajax = false)
- {
- $tp = e107::getParser();
- $controller = $this->getController();
- $request = $controller->getRequest();
- $id = $this->getElementId();
- $tree = $options = array();
- $tree[$id] = $controller->getTreeModel();
- // if going through confirm screen - no JS confirm
- $controller->setFieldAttr('options', 'noConfirm', $controller->deleteConfirmScreen);
- $options[$id] = array(
- 'id' => $this->getElementId(), // unique string used for building element ids, REQUIRED
- 'pid' => $controller->getPrimaryName(), // primary field name, REQUIRED
- //'url' => e_SELF, default
- 'query' => $controller->getFormQuery(), // work around - see form in newspost.php (submitted news)
- //'query' => $request->buildQueryString(array(), true, 'ajax_used'), - ajax_used is now removed from QUERY_STRING - class2
- 'head_query' => $request->buildQueryString('field=[FIELD]&asc=[ASC]&from=[FROM]', false), // without field, asc and from vars, REQUIRED
- 'np_query' => $request->buildQueryString(array(), false, 'from'), // without from var, REQUIRED for next/prev functionality
- 'legend' => $controller->getPluginTitle(), // hidden by default
- 'form_pre' => !$ajax ? $this->renderFilter($tp->post_toForm(array($controller->getQuery('searchquery'), $controller->getQuery('filter_options'))), $controller->getMode().'/'.$controller->getAction()) : '', // needs to be visible when a search returns nothing
- 'form_post' => '', // markup to be added after closing form element
- 'fields' => $controller->getFields(), // see e_admin_ui::$fields
- 'fieldpref' => $controller->getFieldPref(), // see e_admin_ui::$fieldpref
- 'table_pre' => '', // markup to be added before opening table element
- 'table_post' => !$tree[$id]->isEmpty() ? $this->renderBatch($controller->getBatchDelete(),$controller->getBatchCopy(),$controller->getBatchLink(),$controller->getBatchFeaturebox()) : '',
- 'fieldset_pre' => '', // markup to be added before opening fieldset element
- 'fieldset_post' => '', // markup to be added after closing fieldset element
- 'perPage' => $controller->getPerPage(), // if 0 - no next/prev navigation
- 'from' => $controller->getQuery('from', 0), // current page, default 0
- 'field' => $controller->getQuery('field'), //current order field name, default - primary field
- 'asc' => $controller->getQuery('asc', 'desc'), //current 'order by' rule, default 'asc'
- );
- return $this->renderListForm($options, $tree, $ajax);
- }
- public function getConfirmDelete($ids, $ajax = false)
- {
- $controller = $this->getController();
- $request = $controller->getRequest();
- $fieldsets = array();
- $forms = array();
- $id_array = explode(',', $ids);
- $delcount = count($id_array);
-
- if(!empty($controller->deleteConfirmMessage))
- {
- e107::getMessage()->addWarning(str_replace("[x]","<b>".$delcount."</b>", $controller->deleteConfirmMessage));
- }
- else
- {
- e107::getMessage()->addWarning(str_replace("[x]","<b>".$delcount."</b>",LAN_UI_DELETE_WARNING));
- }
-
- $fieldsets['confirm'] = array(
- 'fieldset_pre' => '', // markup to be added before opening fieldset element
- 'fieldset_post' => '', // markup to be added after closing fieldset element
- 'table_head' => '', // markup between <thead> tag
- // Colgroup Example: array(0 => array('class' => 'label', 'style' => 'text-align: left'), 1 => array('class' => 'control', 'style' => 'text-align: left'));
- 'table_colgroup' => '', // array to be used for creating markup between <colgroup> tag (<col> list)
- 'table_pre' => '', // markup to be added before opening table element
- 'table_post' => '', // markup to be added after closing table element
- 'table_rows' => '', // rows array (<td> tags)
- 'table_body' => '', // string body - used only if rows empty
- 'pre_triggers' => '',
- 'triggers' => array('hidden' => $this->hidden('etrigger_delete['.$ids.']', $ids), 'delete_confirm' => array(LAN_CONFDELETE, 'confirm', $ids), 'cancel' => array(LAN_CANCEL, 'cancel')),
- );
- if($delcount > 1)
- {
- $fieldsets['confirm']['triggers']['hidden'] = $this->hidden('etrigger_batch', 'delete');
- }
- $forms[$id] = array(
- 'id' => $this->getElementId(), // unique string used for building element ids, REQUIRED
- 'url' => e_SELF, // default
- 'query' => $request->buildQueryString(array(), true, 'ajax_used'), // - ajax_used is now removed from QUERY_STRING - class2
- 'legend' => $controller->addTitle(LAN_UI_DELETE_LABEL), // hidden by default
- 'form_pre' => '', // markup to be added before opening form element
- 'form_post' => '', // markup to be added after closing form element
- 'header' => '', // markup to be added after opening form element
- 'footer' => '', // markup to be added before closing form element
- 'fieldsets' => $fieldsets,
- );
- return $this->renderForm($forms, $ajax);
- }
- function renderFilter($current_query = array(), $location = '', $input_options = array())
- {
- if(!$input_options) $input_options = array('size' => 20);
- if(!$location)
- {
- $location = 'main/list'; //default location
- }
- $l = e107::getParser()->post_toForm(explode('/', $location));
- if(!is_array($input_options))
- {
- parse_str($input_options, $input_options);
- }
- $input_options['id'] = false;
- $input_options['class'] = 'tbox input-text filter ';
- $controller = $this->getController();
- $filter_pre = vartrue($controller->preFiliterMarkup);
- $filter_post = vartrue($controller->postFiliterMarkup);
- $filter_preserve_var = array();
- // method requires controller - stanalone advanced usage not possible
- if($this->getController())
- {
- $get = $this->getController()->getQuery();
- foreach ($get as $key => $value)
- {
- if($key == 'searchquery' || $key == 'filter_options' || $key == 'etrigger_filter') continue;
- $key = preg_replace('/[^\w]/', '', $key);
- $filter_preserve_var[] = $this->hidden($key, rawurlencode($value));
- }
- }
- else
- {
- $filter_preserve_var[] = $this->hidden('mode', $l[0]);
- $filter_preserve_var[] = $this->hidden('action', $l[1]);
- }
- $text = "
- <form method='get' action='".e_SELF."'>
- <fieldset class='e-filter'>
- <legend class='e-hideme'>".LAN_LABEL_LABEL_SELECTED."</legend>
- ".$filter_pre."
- <div class='row-fluid'>
- <div class='left form-inline span8' style='margin-top:10px;margin-bottom:-10px;'>
- ".$this->text('searchquery', $current_query[0], 50, $input_options)."<i class='fa fa-search searchquery'></i>
- ".$this->select_open('filter_options', array('class' => 'e-tip tbox select filter', 'id' => false, 'title'=>'Filter the results below'))."
- ".$this->option(LAN_FILTER_LABEL_DISPLAYALL, '')."
- ".$this->option(LAN_FILTER_LABEL_CLEAR, '___reset___')."
- ".$this->renderBatchFilter('filter', $current_query[1])."
- ".$this->select_close()."
- <div class='e-autocomplete'></div>
- ".implode("\n", $filter_preserve_var)."
- ".$this->admin_button('etrigger_filter', 'etrigger_filter', 'filter e-hide-if-js', LAN_FILTER, array('id' => false))."
- <span class='indicator' style='display: none;'>
- <img src='".e_IMAGE_ABS."generic/loading_16.gif' class='icon action S16' alt='".LAN_LOADING."' />
- </span>
- </div>
- <div class='span4 text-right' style='margin-top:10px;margin-bottom:-10px;padding-top:15px;padding-right:5px'>";
-
- // Let Admin know which language table is being saved to. (avoid default table overwrites)
- if(e107::getConfig()->get('multilanguage'))
- {
- $curTable = $controller->getTableName();
- if($curTable != e107::getDb()->db_IsLang($curTable))
- {
- $lang = e107::getDb()->mySQLlanguage;
- }
- else
- {
- $lang = e107::getConfig()->get('sitelanguage');
- }
-
- $def = deftrue('LAN_UI_USING_DATABASE_TABLE','Using [x] database table');
- $diz = e107::getParser()->lanVars($def, $lang); // "Using ".$lang." database table";
- $text .= "<span class='e-tip' title=\"".$diz."\">";
- $text .= e107::getParser()->toGlyph('fa-hdd-o'); // '<i class="icon-hdd"></i> ';
- $text .= e107::getLanguage()->toNative($lang)."</span>";
- }
-
- $text .= "
- </div>
- </div>
- ".$filter_post."
- </fieldset>
- </form>
- ";
-
- e107::js('core','scriptaculous/controls.js','prototype', 2);
- //TODO - external JS
- e107::js('footer-inline',"
-
- //autocomplete fields
- \$\$('input[name=searchquery]').each(function(el, cnt) {
- if(!cnt) el.activate();
- else return;
- new Ajax.Autocompleter(el, el.next('div.e-autocomplete'), '".e_SELF."?mode=".$l[0]."&action=filter', {
- paramName: 'searchquery',
- minChars: 2,
- frequency: 0.5,
- afterUpdateElement: function(txt, li) {
- var cfrm = el.up('form'), cont = cfrm.next('.e-container');
- if(!cont) {
- return;
- }
- cfrm.submitForm(cont);
- },
- indicator: el.next('span.indicator'),
- parameters: 'ajax_used=1'
- });
- var sel = el.next('select.filter');
- if(sel) {
- sel.observe('change', function (e) {
- var cfrm = e.element().up('form'), cont = cfrm.next('.e-container');
- if(cfrm && cont && e.element().value != '___reset___') {
- e.stop();
- cfrm.submitForm(cont);
- return;
- }
- e107Helper.selectAutoSubmit(e.element());
- });
- }
- });
- ",'prototype');
-
- // TODO implement ajax queue
- // FIXME - dirty way to register events after ajax update - DO IT RIGHT - see all.jquery, create object
- // and use handler, re-register them global after ajax update (context)
- e107::js('footer-inline',"
- var filterRunning = false, request;
- var applyAfterAjax = function(context) {
- \$('.e-hideme', context).hide();
- \$('.e-expandit', context).show();
- \$('.e-expandit', context).click(function () {
- var href = (\$(this).is('a')) ? \$(this).attr('href') : '';
- if(href == '' && \$(this).attr('data-target'))
- {
- href = '#' + \$(this).attr('data-target');
- }
- if(href === '#' || href == '')
- {
- idt = \$(this).nextAll('div');
- \$(idt).toggle('slow');
- return true;
- }
- //var id = $(this).attr('href');
- \$(href).toggle('slow');
- return false;
- });
- \$('input.toggle-all', context).click(function(evt) {
- var selector = 'input[type=\"checkbox\"].checkbox';
- if(\$(this).val().startsWith('jstarget:')) {
- selector = 'input[type=\"checkbox\"][name^=\"' + \$(this).val().split(/jstarget\:/)[1] + '\"]';
- }
-
- if(\$(this).is(':checked')){
- \$(selector).attr('checked', 'checked');
- }
- else{
- \$(selector).removeAttr('checked');
- }
- });
- };
- var searchQueryHandler = function (e) {
- var el = \$(this), frm = el.parents('form'), cont = frm.nextAll('.e-container');
- if(cont.length < 1 || frm.length < 1 || (el.val().length > 0 && el.val().length < 3)) return;
- e.preventDefault();
-
- if(filterRunning && request) request.abort();
- filterRunning = true;
-
- cont.css({ opacity: 0.5 });
-
- request = \$.get(frm.attr('action'), frm.serialize(), function(data){
- filterRunning = false;
- setTimeout(function() {
- if(filterRunning) {
- //cont.css({ opacity: 1 });
- return;
- }
- cont.html(data).css({ opacity: 1 });
- applyAfterAjax(cont);
- }, 700);
- }, 'html')
- .error(function() {
- filterRunning = false;
- cont.css({ opacity: 1 });
- });
- };
- \$('#searchquery').on('keyup', searchQueryHandler);
- ", 'jquery');
- return $text;
- }
- // FIXME - use e_form::batchoptions(), nice way of buildig batch dropdown - news administration show_batch_options()
- function renderBatch($allow_delete = false,$allow_copy= false, $allow_url=false, $allow_featurebox=false)
- {
-
- // $allow_copy = TRUE;
-
- $fields = $this->getController()->getFields();
- if(!varset($fields['checkboxes']))
- {
- $mes = e107::getMessage();
- $mes->add("Cannot display Batch drop-down as 'checkboxes' was not found in \$fields array.", E_MESSAGE_DEBUG);
- return '';
- }
-
- // FIX - don't show FB option if plugin not installed
- if(!e107::isInstalled('featurebox'))
- {
- $allow_featurebox = false;
- }
-
- // TODO - core ui-batch-option class!!! REMOVE INLINE STYLE!
- // XXX Quick Fix for styling - correct.
- $text = "
- <div class='navbar navbar-inner left' style='padding-left:30px; padding-top:6px; margin-top:-20px;border-top:0px'>
- <img src='".e_IMAGE_ABS."generic/branchbottom.gif' alt='' class='icon action' />
- ".$this->select_open('etrigger_batch', array('class' => 'tbox select batch e-autosubmit reset', 'id' => false))."
- ".$this->option(LAN_BATCH_LABEL_SELECTED, '', false)."
- ".($allow_copy ? $this->option(LAN_COPY, 'copy', false, array('class' => 'ui-batch-option class', 'other' => 'style="padding-left: 15px"')) : '')."
- ".($allow_delete ? $this->option(LAN_DELETE, 'delete', false, array('class' => 'ui-batch-option class', 'other' => 'style="padding-left: 15px"')) : '')."
- ".($allow_url ? $this->option(LAN_UI_BATCH_CREATELINK, 'url', false, array('class' => 'ui-batch-option class', 'other' => 'style="padding-left: 15px"')) : '')."
- ".($allow_featurebox ? $this->option(LAN_PLUGIN_FEATUREBOX_BATCH, 'featurebox', false, array('class' => 'ui-batch-option class', 'other' => 'style="padding-left: 15px"')) : '')."
-
- ".$this->renderBatchFilter('batch')."
- ".$this->select_close()."
- ".$this->admin_button('e__execute_batch', 'e__execute_batch', 'batch e-hide-if-js', LAN_GO, array('id' => false))."
- </div>
- ";
- return $text;
- }
- // TODO - do more
- function renderBatchFilter($type='batch', $selected = '') // Common function used for both batches and filters.
- {
- $optdiz = array('batch' => LAN_BATCH_LABEL_PREFIX.' ', 'filter'=> LAN_FILTER_LABEL_PREFIX.' ');
- $table = $this->getController()->getTableName();
- $text = '';
- $textsingle = '';
-
- foreach($this->getController()->getFields() as $key=>$val)
- {
- if(!varset($val[$type]))
- {
- continue;
- }
- $option = array();
- $parms = vartrue($val['writeParms'], array());
- if(is_string($parms)) parse_str($parms, $parms);
- switch($val['type'])
- {
- case 'bool':
- case 'boolean': //TODO modify description based on $val['parm]
- if(vartrue($parms['reverse'])) // reverse true/false values;
- {
- $option['bool__'.$key.'__0'] = LAN_YES; // see newspost.php : news_allow_comments for an example.
- $option['bool__'.$key.'__1'] = LAN_NO;
- }
- else
- {
- $option['bool__'.$key.'__1'] = LAN_YES;
- $option['bool__'.$key.'__0'] = LAN_NO;
- }
-
- if($type == 'batch')
- {
- $option['boolreverse__'.$key] = LAN_BOOL_REVERSE;
- }
- break;
-
- case 'comma':
- // TODO lan
- if(!isset($parms['__options'])) $parms['__options'] = array();
- if(!is_array($parms['__options'])) parse_str($parms['__options'], $parms['__options']);
- $opts = $parms['__options'];
- unset($parms['__options']); //remove element options if any
-
- $options = $parms ? $parms : array();
- if(empty($options)) continue;
-
-
- if($type == 'batch')
- {
- $_option = array();
- if(isset($options['addAll']))
- {
- $option['attach_all__'.$key] = vartrue($options['addAll'], '(add all)');
- unset($options['addAll']);
- }
- if(isset($options['clearAll']))
- {
- $_option['deattach_all__'.$key] = vartrue($options['clearAll'], '(clear all)');
- unset($options['clearAll']);
- }
-
- if(vartrue($opts['simple']))
- {
- foreach ($options as $value)
- {
- $option['attach__'.$key.'__'.$value] = 'Add '.$value;
- $_option['deattach__'.$key.'__'.$value] = 'Remove '.$value;
- }
- }
- else
- {
- foreach ($options as $value => $label)
- {
- $option['attach__'.$key.'__'.$value] = 'Add '.$label;
- $_option['deattach__'.$key.'__'.$value] = 'Remove '.$label;
- }
- }
- $option = array_merge($option, $_option);
- unset($_option);
- }
- else
- {
- unset($options['addAll'], $options['clearAll']);
- if(vartrue($opts['simple']))
- {
- foreach($options as $k)
- {
- $option[$key.'__'.$k] = $k;
- }
- }
- else
- {
- foreach($options as $k => $name)
- {
- $option[$key.'__'.$k] = $name;
- }
- }
- }
- break;
-
- case 'templates':
- case 'layouts':
- $parms['raw'] = true;
- $val['writeParms'] = $parms;
- $tmp = $this->renderElement($key, '', $val);
- if(is_array($tmp))
- {
- foreach ($tmp as $k => $name)
- {
- $option[$key.'__'.$k] = $name;
- }
- }
- break;
- case 'dropdown': // use the array $parm;
- if(!is_array(varset($parms['__options']))) parse_str($parms['__options'], $parms['__options']);
- $opts = $parms['__options'];
- if(vartrue($opts['multiple']))
- {
- // no batch support for multiple, should have some for filters soon
- continue;
- }
- unset($parms['__options']); //remove element options if any
- foreach($parms as $k => $name)
- {
- $option[$key.'__'.$k] = $name;
- }
- break;
- case 'lanlist': // use the array $parm;
- if(!is_array(varset($parms['__options']))) parse_str($parms['__options'], $parms['__options']);
- $opts = $parms['__options'];
- if(vartrue($opts['multiple']))
- {
- // no batch support for multiple, should have some for filters soon
- continue;
- }
- $options = e107::getLanguage()->getLanSelectArray();
- foreach($options as $code => $name)
- {
- $option[$key.'__'.$code] = $name;
- }
- break;
- case 'datestamp':
- //TODO today, yesterday, this-month, last-month .
-
- $dateFilters = array (
- 'hour' => "Past Hour",
- "day" => "Past 24 hours",
- "week" => "Past Week",
- "month" => "Past Month",
- "year" => "Past Year"
- );
-
- foreach($dateFilters as $k => $name)
- {
- $option['datestamp__'.$key.'__'.$k] = $name;
- // $option['bool__'.$key.'__0'] = LAN_NO;
- // $option[$key.'__'.$k] = $name;
- }
- break;
- case 'userclass':
- $classes = e107::getUserClass()->uc_required_class_list(vartrue($parms['classlist'], 'public,nobody,guest,admin,main,classes'));
- foreach($classes as $k => $name)
- {
- $option[$key.'__'.$k] = $name;
- }
- break;
- case 'userclasses':
- $classes = e107::getUserClass()->uc_required_class_list(vartrue($parms['classlist'], 'public,nobody,guest,admin,main,classes'));
- $_option = array();
-
- if($type == 'batch')
- {
- // FIXME Lan
- foreach ($classes as $k => $v)
- {
- $option['ucadd__'.$key.'__'.$k] = LAN_ADD.' '.$v;
- $_option['ucremove__'.$key.'__'.$k] = 'Remove '.$v;
- }
- $option['ucaddall__'.$key] = '(add all)';
- $_option['ucdelall__'.$key] = '(clear all)';
- $option = array_merge($option, $_option);
- }
- else
- {
- foreach ($classes as $k => $v)
- {
- $option[$key.'__'.$k] = $v;
- }
- }
-
- unset($_option);
- break;
- case 'method':
- $method = $key;
- $list = call_user_func_array(array($this, $method), array('', $type, $parms));
- if(is_array($list))
- {
- //check for single option
- if(isset($list['singleOption']))
- {
- $textsingle .= $list['singleOption'];
- continue;
- }
- // non rendered options array
- foreach($list as $k => $name)
- {
- $option[$key.'__'.$k] = $name;
- }
- }
- elseif(!empty($list)) //optgroup, continue
- {
- $text .= $list;
- continue;
- }
- break;
- case 'user': // TODO - User Filter
-
- $sql = e107::getDb();
- $field = $val['field'];
-
- $query = "SELECT d.".$field.", u.user_name FROM #".$val['table']." AS d LEFT JOIN #user AS u ON d.".$field." = u.user_id GROUP BY d.".$field." ORDER BY u.user_name";
- $row = $sql->retrieve($query,true);
- foreach($row as $data)
- {
- $k = $data[$field];
- if($k == 0)
- {
- $option[$key.'__'.$k] = "(".LAN_ANONYMOUS.")";
- }
- else
- {
- $option[$key.'__'.$k] = vartrue($data['user_name'],'Unknown');
- }
-
-
- }
- break;
- }
- if(count($option) > 0)
- {
- $text .= "\t".$this->optgroup_open($optdiz[$type].defset($val['title'], $val['title']), varset($disabled))."\n";
- foreach($option as $okey=>$oval)
- {
- $text .= $this->option($oval, $okey, $selected == $okey)."\n";
- }
- $text .= "\t".$this->optgroup_close()."\n";
- }
- }
- return $textsingle.$text;
- }
- public function getElementId()
- {
- $controller = $this->getController();
- return str_replace('_', '-', ($controller->getPluginName() == 'core' ? 'core-'.$controller->getTableName() : 'plugin-'.$controller->getPluginName()));
- }
- /**
- * @return e_admin_ui
- */
- public function getController()
- {
- return $this->_controller;
- }
- }
- include_once(e107::coreTemplatePath('admin_icons'));
- /**
- * TODO:
- * 1. [DONE - a good start] move abstract peaces of code to the proper classes
- * 2. [DONE - at least for alpha release] remove duplicated code (e_form & e_admin_form_ui), refactoring
- * 3. make JS Manager handle Styles (.css files and inline CSS)
- * 4. [DONE] e_form is missing some methods used in e_admin_form_ui
- * 5. [DONE] date convert needs string-to-datestamp auto parsing, strptime() is the solution but needs support for
- * Windows and PHP < 5.1.0 - build custom strptime() function (php_compatibility_handler.php) on this -
- * http://sauron.lionel.free.fr/?page=php_lib_strptime (bad license so no copy/paste is allowed!)
- * 6. [DONE - read/writeParms introduced ] $fields[parms] mess - fix it, separate list/edit mode parms somehow
- * 7. clean up/document all object vars (e_admin_ui, e_admin_dispatcher)
- * 8. [DONE hopefully] clean up/document all parameters (get/setParm()) in controller and model classes
- * 9. [DONE] 'ip' field type - convert to human readable format while showing/editing record
- * 10. draggable (or not?) ordering (list view)
- * 11. [DONE] realtime search filter (typing text) - like downloads currently
- * 12. [DONE] autosubmit when 'filter' dropdown is changed (quick fix?)
- * 13. tablerender captions
- * 14. [DONE] textareas auto-height
- * 15. [DONE] multi JOIN table support (optional), aliases
- * 16. tabs support (create/edit view)
- * 17. tree list view (should handle cases like Site Links admin page)
- */
-
- ?>