array( 'list_name' => 'message_list', 'selection_id' => 'uid', 'vertical' => array( 'checkmail' => array('label' => 'checkmail') ), 'horizontal' => array( 'archive' => array('label' => 'archive.buttontext', 'plugin' => true, 'condition' => 'config:archive_folder !== false'), 'delete' => array('label' => 'delete'), 'forward' => array('label' => 'forward'), 'markasjunk' => array('label' => 'markasjunk.markasjunk', 'plugin' => true), 'move' => array('label' => 'moveto'), 'reply' => array('label' => 'reply'), 'reply-all' => array('label' => 'replyall'), 'swipe-flagged' => array('label' => 'swipe.markasflagged'), 'swipe-read' => array('label' => 'swipe.markasread'), 'swipe-select' => array('label' => 'select') ) ), 'contactlist' => array( 'list_name' => 'contact_list', 'selection_id' => 'cid', 'vertical' => array(), 'horizontal' => array( 'vcard_attachments' => array('label' => 'vcard_attachments.forwardvcard', 'plugin' => true), 'compose' => array('label' => 'compose'), 'delete' => array('label' => 'delete'), 'swipe-select' => array('label' => 'select') ) ), 'none' => null ); private $rcube; private $list_type; public function init() { $this->rcube = rcube::get_instance(); $this->add_texts('localization/'); switch ($this->rcube->task) { case 'addressbook': $this->list_type = 'contactlist'; break; case 'mail': $this->list_type = 'messagelist'; break; default: $this->list_type = 'none'; } $this->add_hook('ready', array($this, 'setup')); $this->register_action('plugin.swipe.save_settings', array($this, 'save_settings')); } public function setup() { if ($this->rcube->action != '') { return; } $this->_load_config(); $this->menu_file = '/' . $this->local_skin_path() . '/includes/menu.html'; $filepath = slashify($this->home) . $this->menu_file; if (is_file($filepath) && is_readable($filepath)) { // Allow other plugins to interact with the actions list $data = rcube::get_instance()->plugins->exec_hook('swipe_actions', array('list_type' => $this->list_type, 'actions' => $this->actions[$this->list_type])); $this->list_type = $data['list_type']; $this->actions[$this->list_type] = $data['actions']; if (empty($this->actions[$this->list_type])) { // no swipe actions found, disable the plugin return; } $config = $this->config[$this->list_type]; $this->rcube->output->set_env('swipe_actions', array( 'left' => $config['left'], 'right' => $config['right'], 'down' => $config['down'] )); $this->rcube->output->set_env('swipe_list_name', $this->actions[$this->list_type]['list_name']); $this->rcube->output->set_env('swipe_selection_id', $this->actions[$this->list_type]['selection_id']); $this->include_stylesheet($this->local_skin_path() . '/swipe.css'); $this->include_script('swipe.js'); $this->rcube->output->add_label('swipe.swipeoptions', 'swipe.markasflagged', 'swipe.markasunflagged', 'swipe.markasread', 'swipe.markasunread', 'refresh', 'moveto', 'reply', 'replyall', 'forward', 'select', 'swipe.deselect', 'compose'); if ($this->_allowed_action('*')) { // add swipe actions link to the menu $this->add_button(array( 'command' => 'plugin.swipe.options', 'type' => 'link', 'class' => 'button swipe disabled', 'classact' => 'button swipe', 'title' => 'swipe.swipeoptions', 'innerclass' => 'inner', 'label' => 'swipe.swipeoptions' ), 'listcontrols'); // add swipe actions popup menu $this->rcube->output->add_handler('swipeoptionslist', array($this, 'options_list')); $html = $this->rcube->output->just_parse("menu_file\" skinpath=\"plugins/swipe\" />"); $this->rcube->output->add_footer($html); } } } public function options_list($args) { $axis = $args['direction'] == 'down' ? 'vertical' : 'horizontal'; $swipe_actions = $this->actions[$this->list_type][$axis]; $args['id'] = 'swipeoptions-' . $args['direction']; $args['name'] = 'swipe_' . $args['direction']; $options = array(); foreach ($swipe_actions as $action => $info) { if (!$this->_allowed_action($args['direction'], $action, $info)) { continue; } $options[$action] = $this->gettext($info['label']); } asort($options); // don't add none if there are no available actions, JS detects empty lists and hides the option if (!empty($options)) { $options = array('none' => $this->gettext('none')) + $options; } $config = $this->config[$this->list_type]; switch ($args['type']) { case 'radio': foreach ($options as $val => $text) { $fieldid = $args['id'] . '-' . $val; $radio = new html_radiobutton(array('name' => $args['name'], 'id' => $fieldid, 'class' => $val, 'value' => $val)); $radio = $radio->show($config[$args['direction']]); $field = $radio . html::label($fieldid, $text); } break; case 'select': $select = new html_select($args); $select->add(array_values($options), array_keys($options)); $field = $select->show($config[$args['direction']]); break; } return $field; } public function save_settings() { $this->_load_config(); // Allow other plugins to interact with the actions list $data = rcube::get_instance()->plugins->exec_hook('swipe_actions', array('list_type' => $this->list_type, 'actions' => $this->actions[$this->list_type])); $this->list_type = $data['list_type']; $save = false; foreach (array('left', 'right', 'down') as $direction) { if (($prop = rcube_utils::get_input_value('swipe_' . $direction, rcube_utils::INPUT_POST)) && $this->_allowed_action($direction)) { $this->config[$this->list_type][$direction] = $prop; $save = true; } } if ($save) { rcube::get_instance()->user->save_prefs(array('swipe_actions' => $this->config)); } } private function _load_config() { $this->dont_override = (array) $this->rcube->config->get('dont_override'); $this->disabled_actions = (array) $this->rcube->config->get('disabled_actions'); $this->laoded_plugins = $this->api->loaded_plugins(); // initialize internal config foreach (array_keys($this->actions) as $list) { if ($list != 'none') { $this->config[$list] = array('left' => 'none', 'right' => 'none', 'down' => 'none'); } } // get user config $config = $this->rcube->config->get('swipe_actions', array()); // remove disabled actions foreach ($config as $list => $opts) { foreach ($opts as $direction => $action) { $axis = $direction == 'down' ? 'vertical' : 'horizontal'; $opts = !empty($this->actions[$list][$axis][$action]) ? $this->actions[$list][$axis][$action] : null; if ($this->_allowed_action($direction, $action, $opts)) { $this->config[$list][$direction] = $action; } } } } private function _allowed_action($direction, $action = '', $opts = null) { $result = true; // Skip the action if it is in disabled_actions config option // Also skip actions from disabled/not configured plugins if (in_array('swipe_actions', $this->dont_override) || in_array('swipe_actions.' . $this->list_type, $this->dont_override) || in_array('swipe_actions.' . $this->list_type . '.' . $direction, $this->dont_override)) { $result = false; } elseif (in_array($action, $this->disabled_actions) || in_array($this->rcube->task . $action, $this->disabled_actions)) { $result = false; } elseif (isset($opts['plugin']) && !in_array($action, $this->laoded_plugins)) { // check plugin is enabled $result = false; } // check for special conditions if ($result && !empty($opts['condition']) && !$this->_eval_expression($opts['condition'])) { $result = false; } return $result; } private function _eval_expression($expression) { // from rcmail_output_html::eval_expression() $expression = preg_replace( array( '/session:([a-z0-9_]+)/i', '/config:([a-z0-9_]+)(:([a-z0-9_]+))?/i', '/env:([a-z0-9_]+)/i', '/request:([a-z0-9_]+)/i', '/cookie:([a-z0-9_]+)/i', '/browser:([a-z0-9_]+)/i', ), array( "\$_SESSION['\\1']", "\$this->rcube->config->get('\\1',rcube_utils::get_boolean('\\3'))", "\$this->rcube->output->env['\\1']", "rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)", "\$_COOKIE['\\1']", "\$this->rcmail->output->browser->{'\\1'}", ), $expression ); return eval("return ($expression);"); } }