From 60226a75d8e4a3ee9504da6eab6d8f329bb32e7b Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Tue, 27 Nov 2012 12:13:33 +0100 Subject: [PATCH] Separate the very application-specific output classes from the Roundcube framework; add autoloader for rmail* classes --- program/include/bc.php | 4 +- program/include/iniset.php | 22 +++- program/include/rcmail.php | 20 ++- program/include/rcmail_output.php | 120 +++++++++++++++++ .../rcmail_output_html.php} | 24 ++-- .../rcmail_output_json.php} | 8 +- program/include/rcmail_string_replacer.php | 54 ++++++++ program/lib/Roundcube/rcube_output.php | 123 ++++++++---------- .../lib/Roundcube/rcube_string_replacer.php | 8 +- program/lib/Roundcube/rcube_utils.php | 53 -------- program/steps/mail/func.inc | 2 +- 11 files changed, 279 insertions(+), 159 deletions(-) create mode 100644 program/include/rcmail_output.php rename program/{lib/Roundcube/rcube_output_html.php => include/rcmail_output_html.php} (98%) rename program/{lib/Roundcube/rcube_output_json.php => include/rcmail_output_json.php} (97%) create mode 100644 program/include/rcmail_string_replacer.php diff --git a/program/include/bc.php b/program/include/bc.php index b589135ff..40524be50 100644 --- a/program/include/bc.php +++ b/program/include/bc.php @@ -31,7 +31,7 @@ define('RCUBE_INPUT_GET', rcube_utils::INPUT_GET); define('RCUBE_INPUT_POST', rcube_utils::INPUT_POST); define('RCUBE_INPUT_GPC', rcube_utils::INPUT_GPC); -define('JS_OBJECT_NAME', rcmail::JS_OBJECT_NAME); +define('JS_OBJECT_NAME', rcmail_output::JS_OBJECT_NAME); define('RCMAIL_CHARSET', RCUBE_CHARSET); function get_table_name($table) @@ -126,7 +126,7 @@ function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col) function rcmail_get_edit_field($col, $value, $attrib, $type='text') { - return rcube_utils::get_edit_field($col, $value, $attrib, $type); + return rcube_output::get_edit_field($col, $value, $attrib, $type); } function rcmail_mod_css_styles($source, $container_id, $allow_remote=false) diff --git a/program/include/iniset.php b/program/include/iniset.php index 25ae0189b..be71fc084 100644 --- a/program/include/iniset.php +++ b/program/include/iniset.php @@ -72,8 +72,26 @@ if (set_include_path($include_path) === false) { // include Roundcube Framework require_once 'Roundcube/bootstrap.php'; -// backward compatybility (to be removed) -require_once INSTALL_PATH . 'program/include/rcmail.php'; +// register autoloader for rcmail app classes +spl_autoload_register('rcmail_autoload'); // backward compatybility (to be removed) require_once INSTALL_PATH . 'program/include/bc.php'; + + +/** + * PHP5 autoloader routine for dynamic class loading + */ +function rcmail_autoload($classname) +{ + if (strpos($classname, 'rcmail') === 0) { + $filepath = INSTALL_PATH . "program/include/$classname.php"; + if (is_readable($filepath)) { + include_once $filepath; + return true; + } + } + + return false; +} + diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 3a8c62cec..8e01a2155 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -56,8 +56,6 @@ class rcmail extends rcube private $action_map = array(); - const JS_OBJECT_NAME = 'rcmail'; - const ERROR_STORAGE = -2; const ERROR_INVALID_REQUEST = 1; const ERROR_INVALID_HOST = 2; @@ -321,17 +319,17 @@ class rcmail extends rcube /** * Init output object for GUI and add common scripts. - * This will instantiate a rcube_output_html object and set + * This will instantiate a rcmail_output_html object and set * environment vars according to the current session and configuration * * @param boolean True if this request is loaded in a (i)frame - * @return rcube_output_html Reference to HTML output object + * @return rcube_output Reference to HTML output object */ public function load_gui($framed = false) { // init output page - if (!($this->output instanceof rcube_output_html)) - $this->output = new rcube_output_html($this->task, $framed); + if (!($this->output instanceof rcmail_output_html)) + $this->output = new rcmail_output_html($this->task, $framed); // set refresh interval $this->output->set_env('refresh_interval', $this->config->get('refresh_interval', 0)); @@ -357,12 +355,12 @@ class rcmail extends rcube /** * Create an output object for JSON responses * - * @return rcube_output_json Reference to JSON output object + * @return rcube_output Reference to JSON output object */ public function json_init() { - if (!($this->output instanceof rcube_output_json)) - $this->output = new rcube_output_json($this->task); + if (!($this->output instanceof rcmail_output_json)) + $this->output = new rcmail_output_json($this->task); return $this->output; } @@ -1566,7 +1564,7 @@ class rcmail extends rcube $html_name = $this->Q($foldername) . ($unread ? html::span('unreadcount', sprintf($attrib['unreadwrap'], $unread)) : ''); $link_attrib = $folder['virtual'] ? array() : array( 'href' => $this->url(array('_mbox' => $folder['id'])), - 'onclick' => sprintf("return %s.command('list','%s',this)", rcmail::JS_OBJECT_NAME, $js_name), + 'onclick' => sprintf("return %s.command('list','%s',this)", rcmail_output::JS_OBJECT_NAME, $js_name), 'rel' => $folder['id'], 'title' => $title, ); @@ -1579,7 +1577,7 @@ class rcmail extends rcube (!empty($folder['folders']) ? html::div(array( 'class' => ($is_collapsed ? 'collapsed' : 'expanded'), 'style' => "position:absolute", - 'onclick' => sprintf("%s.command('collapse-folder', '%s')", rcmail::JS_OBJECT_NAME, $js_name) + 'onclick' => sprintf("%s.command('collapse-folder', '%s')", rcmail_output::JS_OBJECT_NAME, $js_name) ), ' ') : '')); $jslist[$folder_id] = array( diff --git a/program/include/rcmail_output.php b/program/include/rcmail_output.php new file mode 100644 index 000000000..36512ad48 --- /dev/null +++ b/program/include/rcmail_output.php @@ -0,0 +1,120 @@ + | + | Author: Aleksander Machniak | + +-----------------------------------------------------------------------+ +*/ + +/** + * Class for output generation + * + * @package Core + * @subpackage View + */ +abstract class rcmail_output extends rcube_output +{ + const JS_OBJECT_NAME = 'rcmail'; + + public $type = 'html'; + public $ajax_call = false; + public $framed = false; + + protected $pagetitle = ''; + protected $object_handlers = array(); + + + /** + * Object constructor + */ + public function __construct($task = null, $framed = false) + { + parent::__construct(); + } + + + /** + * Setter for page title + * + * @param string $title Page title + */ + public function set_pagetitle($title) + { + $this->pagetitle = $title; + } + + + /** + * Getter for the current skin path property + */ + public function get_skin_path() + { + return $this->config->get('skin_path'); + } + + + /** + * Delete all stored env variables and commands + */ + public function reset() + { + parent::reset(); + + $this->object_handlers = array(); + $this->pagetitle = ''; + } + + + /** + * Call a client method + * + * @param string Method to call + * @param ... Additional arguments + */ + abstract function command(); + + + /** + * Add a localized label to the client environment + */ + abstract function add_label(); + + + /** + * Register a template object handler + * + * @param string Object name + * @param string Function name to call + * @return void + */ + public function add_handler($obj, $func) + { + $this->object_handlers[$obj] = $func; + } + + + /** + * Register a list of template object handlers + * + * @param array Hash array with object=>handler pairs + * @return void + */ + public function add_handlers($arr) + { + $this->object_handlers = array_merge($this->object_handlers, $arr); + } + +} diff --git a/program/lib/Roundcube/rcube_output_html.php b/program/include/rcmail_output_html.php similarity index 98% rename from program/lib/Roundcube/rcube_output_html.php rename to program/include/rcmail_output_html.php index f861ff95e..1290e173e 100644 --- a/program/lib/Roundcube/rcube_output_html.php +++ b/program/include/rcmail_output_html.php @@ -2,7 +2,7 @@ /* +-----------------------------------------------------------------------+ - | program/include/rcubeoutput_html.php | + | program/include/rcmail_output_html.php | | | | This file is part of the Roundcube Webmail client | | Copyright (C) 2006-2012, The Roundcube Dev Team | @@ -23,10 +23,10 @@ /** * Class to create HTML page output using a skin template * - * @package Framework + * @package Core * @subpackage View */ -class rcube_output_html extends rcube_output +class rcmail_output_html extends rcmail_output { public $type = 'html'; @@ -82,10 +82,10 @@ class rcube_output_html extends rcube_output $this->set_env('extwin', 1); // add common javascripts - $this->add_script('var '.rcmail::JS_OBJECT_NAME.' = new rcube_webmail();', 'head_top'); + $this->add_script('var '.self::JS_OBJECT_NAME.' = new rcube_webmail();', 'head_top'); // don't wait for page onload. Call init at the bottom of the page (delayed) - $this->add_script(rcmail::JS_OBJECT_NAME.'.init();', 'docready'); + $this->add_script(self::JS_OBJECT_NAME.'.init();', 'docready'); $this->scripts_path = 'program/js/'; $this->include_script('jquery.min.js'); @@ -240,7 +240,7 @@ class rcube_output_html extends rcube_output */ public function add_gui_object($obj, $id) { - $this->add_script(rcmail::JS_OBJECT_NAME.".gui_object('$obj', '$id');"); + $this->add_script(self::JS_OBJECT_NAME.".gui_object('$obj', '$id');"); } @@ -536,7 +536,7 @@ class rcube_output_html extends rcube_output { $out = ''; if (!$this->framed && !empty($this->js_env)) { - $out .= rcmail::JS_OBJECT_NAME . '.set_env('.self::json_serialize($this->js_env).");\n"; + $out .= self::JS_OBJECT_NAME . '.set_env('.self::json_serialize($this->js_env).");\n"; } if (!empty($this->js_labels)) { $this->command('add_label', $this->js_labels); @@ -549,7 +549,7 @@ class rcube_output_html extends rcube_output $parent = $this->framed || preg_match('/^parent\./', $method); $out .= sprintf( "%s.%s(%s);\n", - ($parent ? 'if(window.parent && parent.'.rcmail::JS_OBJECT_NAME.') parent.' : '') . rcmail::JS_OBJECT_NAME, + ($parent ? 'if(window.parent && parent.'.self::JS_OBJECT_NAME.') parent.' : '') . self::JS_OBJECT_NAME, preg_replace('/^parent\./', '', $method), implode(',', $args) ); @@ -1079,7 +1079,7 @@ class rcube_output_html extends rcube_output if ($attrib['command']) { $this->add_script(sprintf( "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');", - rcmail::JS_OBJECT_NAME, + self::JS_OBJECT_NAME, $command, $attrib['id'], $attrib['type'], @@ -1091,7 +1091,7 @@ class rcube_output_html extends rcube_output // make valid href to specific buttons if (in_array($attrib['command'], rcmail::$main_tasks)) { $attrib['href'] = $this->app->url(array('task' => $attrib['command'])); - $attrib['onclick'] = sprintf("return %s.command('switch-task','%s',this,event)", rcmail::JS_OBJECT_NAME, $attrib['command']); + $attrib['onclick'] = sprintf("return %s.command('switch-task','%s',this,event)", self::JS_OBJECT_NAME, $attrib['command']); } else if ($attrib['task'] && in_array($attrib['task'], rcmail::$main_tasks)) { $attrib['href'] = $this->app->url(array('action' => $attrib['command'], 'task' => $attrib['task'])); @@ -1115,7 +1115,7 @@ class rcube_output_html extends rcube_output else if ($command && !$attrib['onclick']) { $attrib['onclick'] = sprintf( "return %s.command('%s','%s',this,event)", - rcmail::JS_OBJECT_NAME, + self::JS_OBJECT_NAME, $command, $attrib['prop'] ); @@ -1648,7 +1648,7 @@ class rcube_output_html extends rcube_output if (empty($attrib['form'])) { $out = $this->form_tag(array( 'name' => "rcmqsearchform", - 'onsubmit' => rcmail::JS_OBJECT_NAME . ".command('search'); return false", + 'onsubmit' => self::JS_OBJECT_NAME . ".command('search'); return false", 'style' => "display:inline"), $out); } diff --git a/program/lib/Roundcube/rcube_output_json.php b/program/include/rcmail_output_json.php similarity index 97% rename from program/lib/Roundcube/rcube_output_json.php rename to program/include/rcmail_output_json.php index fcd52c789..22edce9bd 100644 --- a/program/lib/Roundcube/rcube_output_json.php +++ b/program/include/rcmail_output_json.php @@ -2,7 +2,7 @@ /* +-----------------------------------------------------------------------+ - | program/include/rcube_output_json.php | + | program/include/rc,aiö_output_json.php | | | | This file is part of the Roundcube Webmail client | | Copyright (C) 2008-2012, The Roundcube Dev Team | @@ -23,10 +23,10 @@ /** * View class to produce JSON responses * - * @package Framework + * @package Core * @subpackage View */ -class rcube_output_json extends rcube_output +class rcmail_output_json extends rcmail_output { protected $texts = array(); protected $commands = array(); @@ -158,7 +158,7 @@ class rcube_output_json extends rcube_output { $location = $this->app->url($p); $this->remote_response(sprintf("window.setTimeout(function(){ %s.redirect('%s',true); }, %d);", - rcmail::JS_OBJECT_NAME, $location, $delay)); + self::JS_OBJECT_NAME, $location, $delay)); exit; } diff --git a/program/include/rcmail_string_replacer.php b/program/include/rcmail_string_replacer.php new file mode 100644 index 000000000..4fbc611c9 --- /dev/null +++ b/program/include/rcmail_string_replacer.php @@ -0,0 +1,54 @@ + | + +-----------------------------------------------------------------------+ +*/ + + +/** + * Helper class for turning URLs and email addresses in plaintext content + * into clickable links. + * + * @package Core + * @subpackage Utils + */ +class rcmail_string_replacer extends rcube_string_replacer +{ + /** + * Callback function used to build mailto: links around e-mail strings + * + * This also adds an onclick-handler to open the Rouncube compose message screen on such links + * + * @param array Matches result from preg_replace_callback + * @return int Index of saved string value + * @see rcube_string_replacer::mailto_callback() + */ + public function mailto_callback($matches) + { + $href = $matches[1]; + $suffix = $this->parse_url_brackets($href); + + $i = $this->add(html::a(array( + 'href' => 'mailto:' . $href, + 'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('compose','".rcube::JQ($href)."',this)", + ), rcube::Q($href)) . $suffix); + + return $i >= 0 ? $this->get_replacement($i) : ''; + } + +} \ No newline at end of file diff --git a/program/lib/Roundcube/rcube_output.php b/program/lib/Roundcube/rcube_output.php index 3f881fe06..ca8d83ef3 100644 --- a/program/lib/Roundcube/rcube_output.php +++ b/program/lib/Roundcube/rcube_output.php @@ -28,22 +28,17 @@ abstract class rcube_output { public $browser; - public $type = 'html'; - public $ajax_call = false; - public $framed = false; protected $app; protected $config; - protected $charset = RCUBE_CHARSET; + protected $charset = RCMAIL_CHARSET; protected $env = array(); - protected $pagetitle = ''; - protected $object_handlers = array(); /** * Object constructor */ - public function __construct($task = null, $framed = false) + public function __construct() { $this->app = rcube::get_instance(); $this->config = $this->app->config; @@ -63,16 +58,6 @@ abstract class rcube_output return null; } - /** - * Setter for page title - * - * @param string $title Page title - */ - public function set_pagetitle($title) - { - $this->pagetitle = $title; - } - /** * Setter for output charset. @@ -97,15 +82,6 @@ abstract class rcube_output } - /** - * Getter for the current skin path property - */ - public function get_skin_path() - { - return $this->config->get('skin_path'); - } - - /** * Set environment variable * @@ -137,26 +113,9 @@ abstract class rcube_output public function reset() { $this->env = array(); - $this->object_handlers = array(); - $this->pagetitle = ''; } - /** - * Call a client method - * - * @param string Method to call - * @param ... Additional arguments - */ - abstract function command(); - - - /** - * Add a localized label to the client environment - */ - abstract function add_label(); - - /** * Invoke display_message command * @@ -184,31 +143,6 @@ abstract class rcube_output abstract function send(); - /** - * Register a template object handler - * - * @param string Object name - * @param string Function name to call - * @return void - */ - public function add_handler($obj, $func) - { - $this->object_handlers[$obj] = $func; - } - - - /** - * Register a list of template object handlers - * - * @param array Hash array with object=>handler pairs - * @return void - */ - public function add_handlers($arr) - { - $this->object_handlers = array_merge($this->object_handlers, $arr); - } - - /** * Send HTTP headers to prevent caching a page */ @@ -265,6 +199,59 @@ abstract class rcube_output } + /** + * Create an edit field for inclusion on a form + * + * @param string col field name + * @param string value field value + * @param array attrib HTML element attributes for field + * @param string type HTML element type (default 'text') + * + * @return string HTML field definition + */ + public static function get_edit_field($col, $value, $attrib, $type = 'text') + { + static $colcounts = array(); + + $fname = '_'.$col; + $attrib['name'] = $fname . ($attrib['array'] ? '[]' : ''); + $attrib['class'] = trim($attrib['class'] . ' ff_' . $col); + + if ($type == 'checkbox') { + $attrib['value'] = '1'; + $input = new html_checkbox($attrib); + } + else if ($type == 'textarea') { + $attrib['cols'] = $attrib['size']; + $input = new html_textarea($attrib); + } + else if ($type == 'select') { + $input = new html_select($attrib); + $input->add('---', ''); + $input->add(array_values($attrib['options']), array_keys($attrib['options'])); + } + else if ($attrib['type'] == 'password') { + $input = new html_passwordfield($attrib); + } + else { + if ($attrib['type'] != 'text' && $attrib['type'] != 'hidden') { + $attrib['type'] = 'text'; + } + $input = new html_inputfield($attrib); + } + + // use value from post + if (isset($_POST[$fname])) { + $postvalue = rcube_utils::get_input_value($fname, rcube_utils::INPUT_POST, true); + $value = $attrib['array'] ? $postvalue[intval($colcounts[$col]++)] : $postvalue; + } + + $out = $input->show($value); + + return $out; + } + + /** * Convert a variable into a javascript object notation * diff --git a/program/lib/Roundcube/rcube_string_replacer.php b/program/lib/Roundcube/rcube_string_replacer.php index 0467b866a..584b9f68c 100644 --- a/program/lib/Roundcube/rcube_string_replacer.php +++ b/program/lib/Roundcube/rcube_string_replacer.php @@ -5,7 +5,7 @@ | program/include/rcube_string_replacer.php | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2009, The Roundcube Dev Team | + | Copyright (C) 2009-2012, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -113,11 +113,7 @@ class rcube_string_replacer { $href = $matches[1]; $suffix = $this->parse_url_brackets($href); - - $i = $this->add(html::a(array( - 'href' => 'mailto:' . $href, - 'onclick' => "return ".rcmail::JS_OBJECT_NAME.".command('compose','".rcube::JQ($href)."',this)", - ), rcmail::Q($href)) . $suffix); + $i = $this->add(html::a('mailto:' . $href, rcube::Q($href)) . $suffix); return $i >= 0 ? $this->get_replacement($i) : ''; } diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php index df77dfe42..500f2c371 100644 --- a/program/lib/Roundcube/rcube_utils.php +++ b/program/lib/Roundcube/rcube_utils.php @@ -433,59 +433,6 @@ class rcube_utils } - /** - * Create an edit field for inclusion on a form - * - * @param string col field name - * @param string value field value - * @param array attrib HTML element attributes for field - * @param string type HTML element type (default 'text') - * - * @return string HTML field definition - */ - public static function get_edit_field($col, $value, $attrib, $type = 'text') - { - static $colcounts = array(); - - $fname = '_'.$col; - $attrib['name'] = $fname . ($attrib['array'] ? '[]' : ''); - $attrib['class'] = trim($attrib['class'] . ' ff_' . $col); - - if ($type == 'checkbox') { - $attrib['value'] = '1'; - $input = new html_checkbox($attrib); - } - else if ($type == 'textarea') { - $attrib['cols'] = $attrib['size']; - $input = new html_textarea($attrib); - } - else if ($type == 'select') { - $input = new html_select($attrib); - $input->add('---', ''); - $input->add(array_values($attrib['options']), array_keys($attrib['options'])); - } - else if ($attrib['type'] == 'password') { - $input = new html_passwordfield($attrib); - } - else { - if ($attrib['type'] != 'text' && $attrib['type'] != 'hidden') { - $attrib['type'] = 'text'; - } - $input = new html_inputfield($attrib); - } - - // use value from post - if (isset($_POST[$fname])) { - $postvalue = self::get_input_value($fname, self::INPUT_POST, true); - $value = $attrib['array'] ? $postvalue[intval($colcounts[$col]++)] : $postvalue; - } - - $out = $input->show($value); - - return $out; - } - - /** * Replace all css definitions with #container [def] * and remove css-inlined scripting diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 33ac1a206..ff442ad60 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -790,7 +790,7 @@ function rcmail_plain_body($body, $flowed=false) global $RCMAIL; // make links and email-addresses clickable - $replacer = new rcube_string_replacer; + $replacer = new rcmail_string_replacer; // search for patterns like links and e-mail addresses and replace with tokens $body = $replacer->replace($body);