diff --git a/e107_handlers/file_class.php b/e107_handlers/file_class.php index 35215e160..37399cd46 100644 --- a/e107_handlers/file_class.php +++ b/e107_handlers/file_class.php @@ -813,7 +813,7 @@ class e_file /** * File retrieval function. by Cam. - * @param $file actual path or {e_xxxx} path to file. + * @param $file string actual path or {e_xxxx} path to file. * */ function send($file) @@ -927,9 +927,39 @@ class e_file } } } - } + } + /** + * Return a user specific file directory for the current plugin with the option to create one if it does not exist. + * @param $baseDir + * @param $user - user_id + * @param bool|false $create + * @return bool|string + */ + public function getUserDir($user, $create = false, $subDir = null) + { + $user = intval($user); + $tp = e107::getParser(); + + $baseDir = e_MEDIA.'plugins/'.e_CURRENT_PLUGIN.'/'; + + if(!empty($subDir)) + { + $baseDir .= rtrim($subDir,'/').'/'; + } + + $baseDir .= ($user) ? "user_". $tp->leadingZeros($user, 6) : "anon"; + + if($create == true && !is_dir($baseDir)) + { + mkdir($baseDir, 0755, true); // recursively + } + + $baseDir .= "/"; + + return $baseDir; + } /** @@ -1033,11 +1063,89 @@ class e_file /** * File-class wrapper for upload handler. (Preferred for v2.x) * Process files uploaded in a form post. ie. $_FILES. + * Routine processes the array of uploaded files according to both specific options set by the caller, + * and system options configured by the main admin. + * + * @param string $uploaddir Target directory (checked that it exists, but path not otherwise changed) + * + * @param string $fileinfo Determines any special handling of file name (combines previous $fileinfo and $avatar parameters): + * FALSE - default option; no processing + * @param string $fileinfo = 'attachment+extra_text' Indicates an attachment (related to forum post or PM), and specifies some optional text which is + * incorporated into the final file name (the original $fileinfo parameter). + * @param string $fileinfo = 'prefix+extra_text' - indicates an attachment or file, and specifies some optional text which is prefixed to the file name + * @param string $fileinfo = 'unique' + * - if the proposed destination file doesn't exist, saved under given name + * - if the proposed destination file does exist, prepends time() to the file name to make it unique + * @param string $fileinfo = 'avatar' + * - indicates an avatar is being uploaded (not used - options must be set elsewhere) + * + * @param array $options An array of supplementary options, all of which will be given appropriate defaults if not defined: + * @param $options['filetypes'] Name of file containing list of valid file types + * - Always looks in the admin directory + * - defaults to e_ADMIN.filetypes.xml, else e_ADMIN.admin_filetypes.php for admins (if file exists), otherwise e_ADMIN.filetypes.php for users. + * - FALSE disables this option (which implies that 'extra_file_types' is used) + * @param string $options['file_mask'] Comma-separated list of file types which if defined limits the allowed file types to those which are in both this list and the + * file specified by the 'filetypes' option. Enables restriction to, for example, image files. + * @param bool $options['extra_file_types'] - if is FALSE or undefined, rejects totally unknown file extensions (even if in $options['filetypes'] file). + * if TRUE, accepts totally unknown file extensions which are in $options['filetypes'] file. + * otherwise specifies a comma-separated list of additional permitted file extensions + * @param int $options['final_chmod'] - chmod() to be applied to uploaded files (0644 default) (This routine expects an integer value, so watch formatting/decoding - its normally + * specified in octal. Typically use intval($permissions,8) to convert) + * @param int $options['max_upload_size'] - maximum size of uploaded files in bytes, or as a string with a 'multiplier' letter (e.g. 16M) at the end. + * - otherwise uses $pref['upload_maxfilesize'] if set + * - overriding limit of the smaller of 'post_max_size' and 'upload_max_size' if set in php.ini + * (Note: other parts of E107 don't understand strings with a multiplier letter yet) + * @param string $options['file_array_name'] - the name of the 'input' array - defaults to file_userfile[] - otherwise as set. + * @param int $options['max_file_count'] - maximum number of files which can be uploaded - default is 'unlimited' if this is zero or not set. + * @param bool $options['overwrite'] - if TRUE, existing file of the same name is overwritten; otherwise returns 'duplicate file' error (default FALSE) + * @param int $options['save_to_db'] - [obsolete] storage type - if set and TRUE, uploaded files were saved in the database (rather than as flat files) + * + * @return boolean|array + * Returns FALSE if the upload directory doesn't exist, or various other errors occurred which restrict the amount of meaningful information. + * Returns an array, with one set of entries per uploaded file, regardless of whether saved or + * discarded (not all fields always present) - $c is array index: + * $uploaded[$c]['name'] - file name - as saved to disc + * $uploaded[$c]['rawname'] - original file name, prior to any addition of identifiers etc (useful for display purposes) + * $uploaded[$c]['type'] - mime type (if set - as sent by browser) + * $uploaded[$c]['size'] - size in bytes (should be zero if error) + * $uploaded[$c]['error'] - numeric error code (zero = OK) + * $uploaded[$c]['index'] - if upload successful, the index position from the file_userfile[] array - usually numeric, but may be alphanumeric if coded + * $uploaded[$c]['message'] - text of displayed message relating to file + * $uploaded[$c]['line'] - only if an error occurred, has line number (from __LINE__) + * $uploaded[$c]['file'] - only if an error occurred, has file name (from __FILE__) + * + * On exit, uploaded files should all have been removed from the temporary directory. + * No messages displayed - its caller's responsibility to handle errors and display info to + * user (or can use handle_upload_messages() from this module) + * + * Details of uploaded files are in $_FILES['file_userfile'] (or other array name as set) on entry. + * Elements passed (from PHP) relating to each file: + * ['name'] - the original name + * ['type'] - mime type (if provided - not checked by PHP) + * ['size'] - file size in bytes + * ['tmp_name'] - temporary file name on server + * ['error'] - error code. 0 = 'good'. 1..4 main others, although up to 8 defined for later PHP versions + * Files stored in server's temporary directory, unless another set */ public function getUploaded($uploaddir, $fileinfo = false, $options = null) { require_once(e_HANDLER."upload_handler.php"); - return process_uploaded_files($uploaddir, $fileinfo, $options); + + if($uploaddir == e_UPLOAD || $uploaddir == e_TEMP) + { + $path = $uploaddir; + } + elseif(defined('e_CURRENT_PLUGIN')) + { + $path = $this->getUserDir(USERID, true, str_replace("../",'',$uploaddir)); // .$this->get; + } + else + { + return false; + } + + + return process_uploaded_files($path, $fileinfo, $options); } diff --git a/e107_handlers/mysql_class.php b/e107_handlers/mysql_class.php index ce474532e..cfb8ece8b 100644 --- a/e107_handlers/mysql_class.php +++ b/e107_handlers/mysql_class.php @@ -560,7 +560,7 @@ class e_db_mysql } else { - echo "what happened to db_debug??!!
"; + // echo "what happened to db_debug??!!
"; } } diff --git a/e107_handlers/upload_handler.php b/e107_handlers/upload_handler.php index b14407762..9979909c3 100644 --- a/e107_handlers/upload_handler.php +++ b/e107_handlers/upload_handler.php @@ -455,7 +455,7 @@ function handle_upload_messages(&$upload_array, $errors_only = TRUE, $use_handle * This is the 'legacy' interface, which handles various special cases etc. * It was the only option in E107 0.7.8 and earlier, and is still used in some places in core. * It also attempts to return in the same way as the original, especially when any errors occur - * + * @deprecated * @param string $uploaddir - target directory for file. Defaults to e_FILE/public * @param boolean|string $avatar - sets the 'type' or destination of the file: * FALSE - its a 'general' file @@ -473,7 +473,14 @@ function handle_upload_messages(&$upload_array, $errors_only = TRUE, $use_handle * otherwise returns an array with per-file error codes as appropriate. * On exit, F_MESSAGE is defined with the success/failure message(s) that have been displayed - one file per line */ - +/** + * @Deprecated use e107::getFile()->getUploaded(); + * @param $uploaddir + * @param bool|false $avatar + * @param string $fileinfo + * @param string $overwrite + * @return array|bool + */ function file_upload($uploaddir, $avatar = FALSE, $fileinfo = "", $overwrite = "") { $admin_log = e107::getAdminLog(); diff --git a/e107_handlers/user_select_class.php b/e107_handlers/user_select_class.php index 33b2243f4..18df5f54f 100644 --- a/e107_handlers/user_select_class.php +++ b/e107_handlers/user_select_class.php @@ -42,10 +42,11 @@ class user_select break; } - $text = ""; $text .= ""; - $sql -> db_Select("user", "user_name", $where." ORDER BY user_name"); - while ($row = $sql -> db_Fetch()) { + $sql ->select("user", "user_name", $where." ORDER BY user_name"); + while ($row = $sql ->fetch()) + { $text .= ""; } $text .= ""; @@ -134,7 +135,7 @@ class user_select } else { - $text .= " "; + $text .= " "; } $text .= "".US_LAN_4."...pm = new pmbox_manager; + + $this->prefs = $this->pm->prefs(); + + } + + + + function sc_pm_nav($parm='') + { + $tp = e107::getParser(); + + if(!check_class($this->prefs['pm_class'])) + { + return null; + } + + $mbox = $this->pm->pm_getInfo('inbox'); + + if(!empty($mbox['inbox']['new'])) + { + $count = "".$mbox['inbox']['new'].""; + $icon = $tp->toGlyph('fa-envelope'); + } + else + { + $icon = $tp->toGlyph('fa-envelope-o'); + $count = ''; + } + + + $urlInbox = e107::url('pm','index','', array('query'=>array('mode'=>'inbox'))); + $urlOutbox = e107::url('pm','index','', array('query'=>array('mode'=>'outbox'))); + $urlCompose = e107::url('pm','index','', array('query'=>array('mode'=>'send'))); + + return ''.$icon.$count.' + '; + + } + + + + + function sc_sendpm($parm='') + { + + // global $sysprefs, $pm_prefs; + // $pm_prefs = $sysprefs->getArray("pm_prefs"); + $pm_prefs = e107::getPlugPref('pm'); + + $url = e107::url('pm','index').'?send.'.$parm; + + + if(check_class($pm_prefs['pm_class'])) + { + if(deftrue('FONTAWESOME') && deftrue('BOOTSTRAP')) + { + $img = e107::getParser()->toGlyph('fa-paper-plane',''); + return "{$img} ".LAN_PM_35.""; + } + + + if(file_exists(THEME.'forum/pm.png')) + { + $img = "".LAN_PM.""; + } + else + { + $img = "".LAN_PM.""; + } + + + + return "{$img}"; + } + else + { + return null; + } + + + + + } + + + +} \ No newline at end of file diff --git a/e107_plugins/pm/e_url.php b/e107_plugins/pm/e_url.php new file mode 100644 index 000000000..d936f9dfd --- /dev/null +++ b/e107_plugins/pm/e_url.php @@ -0,0 +1,61 @@ + '^forum/rules/?', + 'sef' => 'forum/rules', + 'redirect' => '{e_PLUGIN}forum/forum.php?f=rules', + ); + + $config['outbox'] = array( + 'regex' => '^forum/stats/?', + 'sef' => 'forum/stats', + 'redirect' => '{e_PLUGIN}forum/forum_stats.php', + ); + + $config['compose'] = array( + 'regex' => '^forum/track/?', + 'sef' => 'forum/track', + 'redirect' => '{e_PLUGIN}forum/forum.php?f=track', + );*/ + + + $config['index'] = array( + 'regex' => '^pm/?(.*)', // matched against url, and if true, redirected to 'redirect' below. + 'sef' => 'pm', // used by e107::url(); to create a url from the db table. + 'redirect' => '{e_PLUGIN}pm/pm.php$1', // file-path of what to load when the regex returns true. + + ); + + + + return $config; + } + + + +} \ No newline at end of file diff --git a/e107_plugins/pm/pm.css b/e107_plugins/pm/pm.css new file mode 100644 index 000000000..4aecf9573 --- /dev/null +++ b/e107_plugins/pm/pm.css @@ -0,0 +1,7 @@ + +tr.pm-unread { font-weight: bold } + +.pm-show h3 { margin-top:5px } +.pm-show h3 small { margin-top:5px } + +div.pm-message { min-height:150px } diff --git a/e107_plugins/pm/pm.php b/e107_plugins/pm/pm.php index 454bdbd59..c8b28e100 100755 --- a/e107_plugins/pm/pm.php +++ b/e107_plugins/pm/pm.php @@ -20,7 +20,10 @@ $retrieve_prefs[] = 'pm_prefs'; -require_once('../../class2.php'); +if (!defined('e107_INIT')) +{ + require_once("../../class2.php"); +} if (!e107::isInstalled('pm')) @@ -34,19 +37,44 @@ if(vartrue($_POST['keyword'])) pm_user_lookup(); } - +e107::css('pm','pm.css'); require_once(e_PLUGIN.'pm/pm_class.php'); require_once(e_PLUGIN.'pm/pm_func.php'); include_lan(e_PLUGIN.'pm/languages/'.e_LANGUAGE.'.php'); e107::getScParser(); -require_once(e_PLUGIN.'pm/pm_shortcodes.php'); +// require_once(e_PLUGIN.'pm/shortcodes/batch/pm_shortcodes.php'); -define('ATTACHMENT_ICON', ""); +if(!defined('ATTACHMENT_ICON')) +{ + if(deftrue('BOOTSTRAP') && deftrue('FONTAWESOME')) + { + define('ATTACHMENT_ICON', $tp->toGlyph('fa-paperclip')); + } + else + { + + define('ATTACHMENT_ICON', ""); + } +} + +if(deftrue('BOOTSTRAP') && deftrue('FONTAWESOME')) +{ + define('PM_DELETE_ICON', $tp->toGlyph('fa-trash')); +} +else +{ + define("PM_DELETE_ICON","".LAN_DELETE.""); +} $qs = explode('.', e_QUERY); $action = varset($qs[0],'inbox'); if (!$action) $action = 'inbox'; +if(!empty($_GET['mode'])) +{ + $action = $tp->filter($_GET['mode']); +} + if($action == 'textarea' || $action == 'input') { if($qs[1] == 'pm_to') { @@ -138,7 +166,7 @@ class pm_extended extends private_message $enc = (check_class($this->pmPrefs['attach_class']) ? "enctype='multipart/form-data'" : ''); // setScVar('pm_handler_shortcodes','pmInfo', $pm_info); - $sc = e107::getScBatch('pm',TRUE); + $sc = e107::getScBatch('pm',true, true); $sc->setVars($pm_info); $PM_SEND_PM = $this->updateTemplate($PM_SEND_PM); @@ -167,10 +195,10 @@ class pm_extended extends private_message $pm_blocks = $this->block_get(); $pmlist = $this->pm_get_inbox(USERID, $start, $this->pmPrefs['perpage']); - + // setScVar('pm_handler_shortcodes', 'pmNextPrev', array('start' => $start, 'total' => $pmlist['total_messages'])); - $sc = e107::getScBatch('pm',TRUE); + $sc = e107::getScBatch('pm',true, 'pm'); $sc->pmNextPrev = array('start' => $start, 'total' => $pmlist['total_messages']); @@ -179,7 +207,7 @@ class pm_extended extends private_message $PM_INBOX_EMPTY = $this->updateTemplate($PM_INBOX_EMPTY); $PM_INBOX_FOOTER = $this->updateTemplate($PM_INBOX_FOOTER); - $txt = "
"; + $txt = ""; $txt .= $tp->parseTemplate($PM_INBOX_HEADER, true, $sc); if($pmlist['total_messages']) @@ -218,7 +246,7 @@ class pm_extended extends private_message $pmlist = $this->pm_get_outbox(USERID, $start, $this->pmPrefs['perpage']); // setScVar('pm_handler_shortcodes', 'pmNextPrev', array('start' => $start, 'total' => $pmlist['total_messages'])); - $sc = e107::getScBatch('pm',TRUE); + $sc = e107::getScBatch('pm', true, 'pm'); $sc->pmNextPrev = array('start' => $start, 'total' => $pmlist['total_messages']); $PM_OUTBOX_HEADER = $this->updateTemplate($PM_OUTBOX_HEADER); @@ -264,15 +292,14 @@ class pm_extended extends private_message include_once(is_readable($tpl_file) ? $tpl_file : e_PLUGIN.'pm/pm_template.php'); $pm_info = $this->pm_get($pmid); - // setScVar('pm_handler_shortcodes','pmInfo', $pm_info); - $sc = e107::getScBatch('pm',TRUE); + $sc = e107::getScBatch('pm',true, 'pm'); $sc->setVars($pm_info); if($pm_info['pm_to'] != USERID && $pm_info['pm_from'] != USERID) { $ns->tablerender(LAN_PM, LAN_PM_60); - require_once(FOOTERF); - exit; + return; + } if($pm_info['pm_read'] == 0 && $pm_info['pm_to'] == USERID) @@ -282,11 +309,22 @@ class pm_extended extends private_message $this->pm_mark_read($pmid, $pm_info); } + $sc->pmMode = $comeFrom; $PM_SHOW = $this->updateTemplate($PM_SHOW); $txt = e107::getParser()->parseTemplate($PM_SHOW, true, $sc); - $ns->tablerender(LAN_PM, $txt); + + if($comeFrom == 'outbox') + { + $bread = array('text'=> LAN_PM_26, 'url'=>e107::url('pm','index').'?mode=outbox'); + } + else + { + $bread = array('text'=> LAN_PM_25, 'url'=>e107::url('pm','index').'?mode=inbox'); + } + + $ns->tablerender(LAN_PM, $this->breadcrumb($bread ,'#'.$pmid).$txt); if (!$comeFrom) { @@ -296,11 +334,16 @@ class pm_extended extends private_message // Need to show inbox or outbox from start if ($comeFrom == 'outbox') { // Show Outbox - $ns->tablerender(LAN_PM." - ".LAN_PM_26, $this->show_outbox(), 'PM'); + + $caption = ''; + if(!deftrue('BOOTSTRAP')){ $caption .= LAN_PM." - ".LAN_PM_26; } + $ns->tablerender($caption, $this->show_outbox(), 'PM'); } else { // Show Inbox - $ns->tablerender(LAN_PM.' - '.LAN_PM_25, $this->show_inbox(), 'PM'); + $caption = ''; + if(!deftrue('BOOTSTRAP')){ $caption .= LAN_PM." - ".LAN_PM_25; } + $ns->tablerender($caption, $this->show_inbox(), 'PM'); } } @@ -318,7 +361,7 @@ class pm_extended extends private_message include(is_readable($tpl_file) ? $tpl_file : e_PLUGIN.'pm/pm_template.php'); $pmBlocks = $this->block_get_user(); // TODO - handle pagination, maybe (is it likely to be necessary?) - $sc = e107::getScBatch('pm',TRUE); + $sc = e107::getScBatch('pm',TRUE, 'pm'); $sc->pmBlocks = $pmBlocks; $PM_BLOCKED_HEADER = $this->updateTemplate($PM_BLOCKED_HEADER); @@ -394,10 +437,12 @@ class pm_extended extends private_message $to_array[$k] = trim($v); } $to_array = array_unique($to_array); + if(count($to_array) == 1) { $_POST['pm_to'] = $to_array[0]; } + if(check_class($this->pmPrefs['multi_class']) && count($to_array) > 1) { foreach($to_array as $to) @@ -436,8 +481,17 @@ class pm_extended extends private_message unset($_POST['receipt']); } } + $totalsize = strlen($_POST['pm_message']); + $maxsize = intval($this->pmPrefs['attach_size']) * 1024; + + + + + + + foreach(array_keys($_FILES['file_userfile']['size']) as $fid) { if($maxsize > 0 && $_FILES['file_userfile']['size'][$fid] > $maxsize) @@ -466,6 +520,29 @@ class pm_extended extends private_message } } + + if(check_class($this->pmPrefs['attach_class'])) + { + $_POST['uploaded'] = $this->processAttachments(); + + foreach($_POST['uploaded'] as $var) + { + if(!empty($var['message'])) + { + $msg .= $var['message']."
"; + } + + } + } + else + { + $msg .= LAN_PM_23.'
'; + unset($_POST['uploaded']); + + } + + +/* if($_FILES['file_userfile']['name'][0]) { if(check_class($this->pmPrefs['attach_class'])) @@ -485,14 +562,60 @@ class pm_extended extends private_message unset($_POST['uploaded']); } } +*/ + $_POST['from_id'] = USERID; + + return $msg.$this->add($_POST); } } + + + function processAttachments() + { + $randnum = rand(1000, 9999); + $type = 'attachment+'.$randnum.'_'; + return e107::getFile()->getUploaded("attachments",$type, array('max_file_count'=>3)); + } + + + + + function breadcrumb($type='',$other) + { + if(!deftrue('BOOTSTRAP')) + { + return null; + } + + $array = array(); + $array[0] = array('text'=>LAN_PM, 'url'=>e107::url('pm','index')); + + if(is_string($type)) + { + $array[1] = array('text'=>$type, 'url'=>null); + } + elseif(is_array($type)) + { + $array[1] = $type; + } + + if($other) + { + $array[2] = array('text'=>$other, 'url'=>null); + } + + return e107::getForm()->breadcrumb($array); + + } + } + + /** * Look up users matching a keyword, output a list of those found * Direct echo @@ -663,7 +786,7 @@ if($message != '') switch ($action) { case 'send' : - $ns->tablerender(LAN_PM, $mes->render() . $pm->show_send($pm_proc_id)); + $ns->tablerender(LAN_PM, $pm->breadcrumb(LAN_PM_35). $mes->render() . $pm->show_send($pm_proc_id)); break; case 'reply' : @@ -672,33 +795,41 @@ switch ($action) { if($pm_info['pm_to'] != USERID) { - $ns->tablerender(LAN_PM, $mes->render() . LAN_PM_56); + $ns->tablerender(LAN_PM, $pm->breadcrumb(LAN_PM_55).$mes->render() . LAN_PM_56); } else { - $ns->tablerender(LAN_PM, $mes->render() . $pm->show_send($pm_info)); + $ns->tablerender(LAN_PM, $pm->breadcrumb(LAN_PM_55). $mes->render() . $pm->show_send($pm_info)); } } else { - $ns->tablerender(LAN_PM, $mes->render() . LAN_PM_57); + $ns->tablerender(LAN_PM, $pm->breadcrumb(LAN_PM_55). $mes->render() . LAN_PM_57); } break; case 'inbox' : - $ns->tablerender(LAN_PM.' - '.LAN_PM_25, $mes->render() . $pm->show_inbox($pm_proc_id), 'PM'); + $caption = LAN_PM; + if(!deftrue('BOOTSTRAP')){ $caption .= ' - '.LAN_PM_25; } + + $ns->tablerender($caption, $pm->breadcrumb(LAN_PM_25). $mes->render() . $pm->show_inbox($pm_proc_id), 'PM'); break; case 'outbox' : - $ns->tablerender(LAN_PM.' - '.LAN_PM_26, $mes->render() . $pm->show_outbox($pm_proc_id), 'PM'); + $caption = LAN_PM; + if(!deftrue('BOOTSTRAP')){ $caption .= ' - '.LAN_PM_26; } + $ns->tablerender($caption, $pm->breadcrumb(LAN_PM_26).$mes->render() . $pm->show_outbox($pm_proc_id), 'PM'); break; case 'show' : + $pm->show_pm($pm_proc_id, $pmSource); break; case 'blocked' : - $ns->tablerender(LAN_PM.' - '.LAN_PM_66, $mes->render() . $pm->showBlocked($pm_proc_id), 'PM'); + $caption = LAN_PM; + if(!deftrue('BOOTSTRAP')){ $caption .= ' - '.LAN_PM_66; } + $ns->tablerender($caption, $pm->breadcrumb('blocked').$mes->render() . $pm->showBlocked($pm_proc_id), 'PM'); break; } diff --git a/e107_plugins/pm/pm_class.php b/e107_plugins/pm/pm_class.php index 006eeac80..a36e432bf 100755 --- a/e107_plugins/pm/pm_class.php +++ b/e107_plugins/pm/pm_class.php @@ -19,6 +19,13 @@ class private_message protected $e107; protected $pmPrefs; + + public function prefs() + { + return $this->pmPrefs; + } + + /** * Constructor * @@ -128,6 +135,7 @@ class private_message { // Send triggered by user - may be immediate or bulk dependent on number of recipients $vars['options'] = ''; if(isset($vars['receipt']) && $vars['receipt']) {$pm_options .= '+rr+'; } + if(isset($vars['uploaded'])) { foreach($vars['uploaded'] as $u) @@ -163,6 +171,9 @@ class private_message 'pm_option' => $pm_options, /* Options associated with PM - '+rr' for read receipt */ 'pm_size' => $pmsize ); + + print_a($info); + print_a($vars); } if(isset($vars['to_userclass']) || isset($vars['to_array'])) @@ -333,12 +344,12 @@ class private_message /** * Convinient url assembling shortcut - */ + *//* public function url($action, $params = array(), $options = array()) { if(strpos($action, '/') === false) $action = 'view/'.$action; e107::getUrl()->create('pm/'.$action, $params, $options); - } + }*/ /** * Send an email to notify of a PM @@ -354,8 +365,10 @@ class private_message { require_once(e_HANDLER.'mail.php'); $subject = LAN_PM_100.SITENAME; - // $pmlink = $this->url('show', 'id='.$pmid, 'full=1&encode=0'); //TODO broken - replace with e_url.php configuration. - $pmlink = SITEURLBASE.e_PLUGIN_ABS."pm/pm.php?show.".$pmid; + + // $pmlink = SITEURLBASE.e_PLUGIN_ABS."pm/pm.php?show.".$pmid; + + $pmlink = e107::url('pm','index').'?show.'.$pmid; $txt = LAN_PM_101.SITENAME."\n\n"; $txt .= LAN_PM_102.USERNAME."\n"; $txt .= LAN_PM_103.$pmInfo['pm_subject']."\n"; @@ -600,11 +613,13 @@ class private_message ORDER BY pm.pm_sent DESC LIMIT ".$from.", ".$limit." "; + if($sql->gen($qry)) { - $total_messages = $sql->total_results; // Total number of messages + $total_messages = $sql->foundRows(); // Total number of messages $ret['messages'] = $sql->db_getList(); } + $ret['total_messages'] = $total_messages; // Should always be defined return $ret; } @@ -653,28 +668,56 @@ class private_message * * @return none * - * @todo Can we use core send routine? */ function send_file($pmid, $filenum) { $pm_info = $this->pm_get($pmid); + $attachments = explode(chr(0), $pm_info['pm_attachments']); + if(!isset($attachments[$filenum])) { - return FALSE; + return false; } + $fname = $attachments[$filenum]; list($timestamp, $fromid, $rand, $file) = explode("_", $fname, 4); - $filename = getcwd()."/attachments/{$fname}"; + + + $filename = false; // getcwd()."/attachments/{$fname}"; + + $pathList = array(); + $pathList[] = e_PLUGIN."pm/attachments/"; // getcwd()."/attachments/"; // legacy path. + $pathList[] = e107::getFile()->getUserDir($fromid, false, 'attachments'); // new media path. + + foreach($pathList as $path) + { + $tPath = $path.$fname; + + if(is_file($tPath)) + { + $filename = $tPath; + break; + } + + } + + if(empty($filename) || !is_file($filename)) + { + return false; + } + if($fromid != $pm_info['pm_from']) { - return FALSE; - } - if(!is_file($filename)) - { - return FALSE; + return false; } + + // e107::getFile()->send($filename); // limited to Media and system folders. Won't work for legacy plugin path. + // exit; + + + @set_time_limit(10 * 60); @e107_ini_set("max_execution_time", 10 * 60); while (@ob_end_clean()); // kill all output buffering else it eats server resources @@ -720,6 +763,12 @@ class private_message } + + + + + + function updateTemplate($template) { diff --git a/e107_plugins/pm/pm_func.php b/e107_plugins/pm/pm_func.php index 712f0ec0e..073155d4f 100755 --- a/e107_plugins/pm/pm_func.php +++ b/e107_plugins/pm/pm_func.php @@ -22,7 +22,14 @@ class pmbox_manager $this->pmDB = e107::getDb(); // $this->pmPrefs = $prefs; - $this->pmPrefs = e107::getPlugPref('pm'); + $this->pmPrefs = e107::pref('pm'); + } + + + public function prefs() + { + return $this->pmPrefs; + } diff --git a/e107_plugins/pm/pm_template.php b/e107_plugins/pm/pm_template.php index 4fe74e9a3..21964c794 100755 --- a/e107_plugins/pm/pm_template.php +++ b/e107_plugins/pm/pm_template.php @@ -27,16 +27,23 @@ if (!defined('e107_INIT')) { exit; } global $sc_style; // Needed for the PM_REPLY shortcode! -if (!defined('PM_READ_ICON')) define('PM_READ_ICON', "".LAN_PM_111.""); -if (!defined('PM_UNREAD_ICON')) define('PM_UNREAD_ICON', "".LAN_PM_27.""); +if(deftrue('BOOTSTRAP') && deftrue('FONTAWESOME')) +{ + define('PM_READ_ICON', e107::getParser()->toGlyph('fa-envelope')); + define('PM_UNREAD_ICON', e107::getParser()->toGlyph('fa-envelope-o')); +} +else +{ + if (!defined('PM_READ_ICON')) define('PM_READ_ICON', "".LAN_PM_111.""); + if (!defined('PM_UNREAD_ICON')) define('PM_UNREAD_ICON', "".LAN_PM_27.""); +} $sc_style['PM_ATTACHMENT_ICON']['pre'] = " "; - -$sc_style['PM_ATTACHMENTS']['pre'] = "
"; +$sc_style['PM_ATTACHMENTS']['pre'] = "
"; $sc_style['PM_ATTACHMENTS']['post'] = "
"; -$sc_style['PM_NEXTPREV']['pre'] = " ".LAN_PM_59; -$sc_style['PM_NEXTPREV']['post'] = ""; +//$sc_style['PM_NEXTPREV']['pre'] = " ".LAN_PM_59; +//$sc_style['PM_NEXTPREV']['post'] = ""; $sc_style['PM_EMOTES']['pre'] = " @@ -111,10 +118,10 @@ $PM_INBOX_HEADER = " "; $PM_INBOX_TABLE = " - + {PM_SELECT} - {PM_READ_ICON} - {PM_SUBJECT=link,inbox}{PM_ATTACHMENT_ICON} + {PM_ATTACHMENT_ICON} + {PM_SUBJECT=link,inbox} {PM_FROM=link} {PM_DATE} {PM_DELETE=inbox} {PM_BLOCK_USER} @@ -129,12 +136,14 @@ $PM_INBOX_EMPTY = " $PM_INBOX_FOOTER = " - + {PM_DELETE_SELECTED} + + {PM_NEXTPREV=inbox} + -{PM_NEXTPREV=inbox} "; @@ -157,8 +166,8 @@ $PM_OUTBOX_HEADER = " $PM_OUTBOX_TABLE = " {PM_SELECT} - {PM_READ_ICON} - {PM_SUBJECT=link,outbox}{PM_ATTACHMENT_ICON} + {PM_ATTACHMENT_ICON} + {PM_SUBJECT=link,outbox} {PM_TO=link} {PM_DATE} {PM_DELETE=outbox} @@ -170,7 +179,7 @@ $PM_OUTBOX_EMPTY = " ".LAN_PM_34." "; - +/* $PM_OUTBOX_FOOTER = " @@ -181,9 +190,24 @@ $PM_OUTBOX_FOOTER = " {PM_NEXTPREV=outbox} +";*/ + +$PM_OUTBOX_FOOTER = " + + + + {PM_DELETE_SELECTED} + + + {PM_NEXTPREV=inbox} + + + + "; + $PM_BLOCKED_HEADER = " @@ -221,29 +245,24 @@ $PM_BLOCKED_FOOTER = " $PM_SHOW = -"
-
+"
+
- + - - {PM_REPLY}
{PM_SUBJECT} +

{PM_SUBJECT} {PM_DATE}

+ {PM_FROM_TO} + {PM_READ} {PM_DELETE}
- {PM_FROM_TO} -
-
- ".LAN_PM_29.":
{PM_DATE}
-
-
- ".LAN_PM_30.":
{PM_READ}
-
-
- {PM_DELETE} +
+
{PM_MESSAGE}
+ {PM_ATTACHMENTS}
{PM_MESSAGE}

{PM_ATTACHMENTS}
+
"; ?> \ No newline at end of file diff --git a/e107_plugins/pm/private_msg_menu.php b/e107_plugins/pm/private_msg_menu.php index 3dacde3ac..0b678ee08 100755 --- a/e107_plugins/pm/private_msg_menu.php +++ b/e107_plugins/pm/private_msg_menu.php @@ -90,7 +90,7 @@ require_once(e_PLUGIN.'pm/pm_func.php'); e107::getScParser(); -require_once(e_PLUGIN.'pm/pm_shortcodes.php'); +require_once(e_PLUGIN.'pm/shortcodes/batch/pm_shortcodes.php'); //setScVar('pm_handler_shortcodes','pmPrefs', $pm_prefs); $pmManager = new pmbox_manager($pm_prefs); @@ -157,7 +157,7 @@ if(!isset($pm_menu_template)) if(check_class($pm_prefs['pm_class'])) { $tp = e107::getParser(); - $sc = e107::getScBatch('pm',TRUE); + $sc = e107::getScBatch('pm',TRUE, 'pm'); $pm_inbox = $pmManager->pm_getInfo('inbox'); diff --git a/e107_plugins/pm/pm_shortcodes.php b/e107_plugins/pm/shortcodes/batch/pm_shortcodes.php old mode 100755 new mode 100644 similarity index 80% rename from e107_plugins/pm/pm_shortcodes.php rename to e107_plugins/pm/shortcodes/batch/pm_shortcodes.php index 579379dc0..f1c679109 --- a/e107_plugins/pm/pm_shortcodes.php +++ b/e107_plugins/pm/shortcodes/batch/pm_shortcodes.php @@ -78,9 +78,9 @@ PM_BLOCKED_DELETE DELETE_BLOCKED_SELECTED */ -if(!class_exists('pm_shortcodes')) +if(!class_exists('plugin_pm_pm_shortcodes')) { - class pm_shortcodes extends e_shortcode // class pm_handler_shortcodes + class plugin_pm_pm_shortcodes extends e_shortcode // class pm_handler_shortcodes { public $pmPrefs; // PM system options public $pmInfo; // Data relating to current PM being displayed - replaced by $var. @@ -89,6 +89,7 @@ if(!class_exists('pm_shortcodes')) public $nextPrev = array(); //XXX In USE ?? // Variables used by nextprev public $pmManager = NULL; // Pointer to pmbox_manager class instance public $pmNextPrev = array(); + public $pmMode = null; //public $var = array(); public function __construct() @@ -98,7 +99,9 @@ if(!class_exists('pm_shortcodes')) $this->pmPrefs = $pm_prefs; // print_a($pm_prefs); require_once(e_PLUGIN."pm/pm_class.php"); + $pmClass = new private_message($pm_prefs); + $blocks = $pmClass->block_get_user(); foreach($blocks as $usr) @@ -225,18 +228,24 @@ if(!class_exists('pm_shortcodes')) { $ret = "
- - - -
+ + ".e107::getForm()->file('file_userfile[]', array('size'=>40, 'multiple'=>'multiple'))." + + "; + /* + $ret .= " - "; + ";*/ return $ret; } return ''; } + + + + public function sc_pm_attachment_icon() { if($this->var['pm_attachments'] != "") @@ -248,6 +257,8 @@ if(!class_exists('pm_shortcodes')) public function sc_pm_attachments() { + $tp = e107::getParser(); + if($this->var['pm_attachments'] != '') { $attachments = explode(chr(0), $this->var['pm_attachments']); @@ -257,7 +268,7 @@ if(!class_exists('pm_shortcodes')) { list($timestamp, $fromid, $rand, $filename) = explode("_", $a, 4); $url = $this->url('action/get', array('id' => $this->var['pm_id'], 'index' => $i)); - $ret .= "{$filename}
"; + $ret .= $tp->toGlyph('fa-paperclip')."{$filename}
"; $i++; } $ret = substr($ret, 0, -3); @@ -335,6 +346,11 @@ if(!class_exists('pm_shortcodes')) public function sc_pm_read($parm = '') { + if($this->pmMode == 'inbox') + { + return; + } + if($this->var['pm_read'] == 0) { return LAN_PM_27; @@ -343,14 +359,14 @@ if(!class_exists('pm_shortcodes')) { return LAN_PM_28; } - require_once(e_HANDLER.'date_handler.php'); + if('lapse' != $parm) { - return convert::convert_date($this->var['pm_read'], $parm); + return e107::getDate()->convert_date($this->var['pm_read'], $parm); } else { - return convert::computeLapse($this->var['pm_read']); + return e107::getDate()->computeLapse($this->var['pm_read']); } } @@ -358,19 +374,19 @@ if(!class_exists('pm_shortcodes')) public function sc_pm_from_to() { $tp = e107::getParser(); - $sc = e107::getScBatch('pm',TRUE); + // $sc = e107::getScBatch('pm',TRUE); - if($this->var['pm_from'] == USERID) + if($this->pmMode == 'outbox') { - $ret = LAN_PM_2.':
'; + $ret = LAN_PM_2.': '; $this->var['user_name'] = $this->var['sent_name']; - $ret .= $tp->parseTemplate("{PM_TO=link}", false, $sc); + $ret .= $this->sc_pm_to('link'); // $tp->parseTemplate("{PM_TO=link}", false, $sc); } else { - $ret = LAN_PM_31.':
'; + $ret = LAN_PM_31.': '; $this->var['user_name'] = $this->var['from_name']; - $ret .= $tp->parseTemplate("{PM_FROM=link}", false, $sc); + $ret .= $this->sc_pm_from('link');// $tp->parseTemplate("{PM_FROM=link}", false, $sc); } return $ret; } @@ -380,7 +396,9 @@ if(!class_exists('pm_shortcodes')) { $tp = e107::getParser(); $ret = $tp->toHTML($this->var['pm_subject'], true, 'USER_TITLE'); + $prm = explode(',',$parm); + if('link' == $prm[0]) { $extra = ''; @@ -395,7 +413,9 @@ if(!class_exists('pm_shortcodes')) $ret = "".$ret.""; */ - $ret = "".$ret.""; + $url = e107::url('pm','index')."?show.{$this->var['pm_id']}{$extra}"; + + $ret = "".$ret.""; } return $ret; } @@ -434,6 +454,20 @@ if(!class_exists('pm_shortcodes')) } } + public function sc_pm_status_class() + { + + if($this->var['pm_read'] > 0 ) + { + return 'pm-read'; + } + else + { + return 'pm-unread'; + } + + } + public function sc_pm_avatar() { @@ -463,23 +497,32 @@ if(!class_exists('pm_shortcodes')) public function sc_pm_delete($parm = '') { + if($this->pmMode !== 'inbox' && $this->pmMode !== 'outbox' && empty($parm)) + { + return ''; + } + + if($parm != '') { $extra = '.'.$parm; } else { - $extra = '.'.($this->var['pm_from'] == USERID ? 'outbox' : 'inbox'); + $extra = '.'.($this->pmMode == 'outbox' ? 'outbox' : 'inbox'); } - if($extra !== 'inbox' && $extra !== 'outbox') return ''; + + $action = $extra == 'outbox' ? 'delete-out' : 'delete-in'; - return "".LAN_DELETE.""; + return "".PM_DELETE_ICON.""; } public function sc_pm_delete_selected() { - return ""; + $tp = e107::getParser(); + return e107::getForm()->button('pm_delete_selected',1,'delete',$tp->toGlyph('fa-trash').LAN_PM_53); + // return ""; } @@ -609,16 +652,93 @@ if(!class_exists('pm_shortcodes')) return ""; } - /** - * Convinient url assembling shortcut - */ - public function url($action, $params = array(), $options = array()) - { - if(strpos($action, '/') === false) $action = 'view/'.$action; - return e107::getUrl()->create('pm/'.$action, $params, $options); + + private function url($route, $params = array(), $options) + { + + if(is_string($params)) + { + parse_str($params,$params); + } + + if(!isset($params['id']) && isset($params['pm_id'])) $params['id'] = $params['pm_id']; + + if(is_string($route)) + { + $route = explode('/', $route, 2); + } + + + + $base = e107::url('pm','index').'?'; + + switch($route[1]) + { + case 'index': + case 'inbox': + return $base.'inbox'; + break; + + case 'outbox': + return $base.'outbox'; + break; + + // we could just remove them all and let only 'message' live + case 'show': + return $base.'show.'.$params['id']; + break; + + case 'message': + return $base.'show.'.$params['id'].'.inbox'; + break; + + case 'sent': + return $base.'show.'.$params['id'].'.outbox'; + break; + + case 'reply': + return $base.'reply.'.$params['id']; + break; + + case 'new': + return $base.'send'; + break; + } + + + + switch($route[1]) + { + case 'delete-in': + return $base.'del.'.$params['id'].'.inbox'; + break; + + case 'delete-out': + return $base.'del.'.$params['id'].'.outbox'; + break; + + case 'delete-blocked': + return $base.'delblocked.'.$params['id']; + break; + + case 'block': + return $base.'block.'.$params['id']; + break; + + case 'unblock': + return $base.'unblock.'.$params['id']; + break; + + case 'get': + return $base.'get.'.$params['id'].'.'.$params['index']; + break; + } + + + } + } - } } diff --git a/e107_plugins/pm/test.css b/e107_plugins/pm/test.css deleted file mode 100644 index 0fc5fc65d..000000000 --- a/e107_plugins/pm/test.css +++ /dev/null @@ -1,40 +0,0 @@ -/* TextboxList sample CSS */ -ul.holder { margin: 0; border: 1px solid #999; overflow: hidden; height: auto !important; height: 1%; padding: 4px 5px 0; } -*:first-child+html ul.holder { padding-bottom: 2px; } * html ul.holder { padding-bottom: 2px; } /* ie7 and below */ -ul.holder li { float: left; list-style-type: none; margin: 0 5px 4px 0; } -ul.holder li.bit-box, ul.holder li.bit-input input { font: 11px "Lucida Grande", "Verdana"; } -ul.holder li.bit-box { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; border: 1px solid #CAD8F3; background: #DEE7F8; padding: 1px 5px 2px; } -ul.holder li.bit-box-focus { border-color: #598BEC; background: #598BEC; color: #fff; } -ul.holder li.bit-input input { width: 150px; margin: 0; border: none; outline: 0; padding: 3px 0 2px; } /* no left/right padding here please */ -ul.holder li.bit-input input.smallinput { width: 20px; } - -/* Facebook demo CSS */ -form, #add { border: 1px solid #999; width: 550px; margin: 50px; padding: 20px 30px 10px; } -form ol { font: 11px "Lucida Grande", "Verdana"; margin: 0; padding: 0; } -form ol li.input-text { margin-bottom: 10px; list-style-type: none; border-bottom: 1px dotted #999; padding-bottom: 10px; } -form ol li.input-text label { font-weight: bold; cursor: pointer; display: block; font-size: 13px; margin-bottom: 10px; } -form ol li.input-text input { width: 500px; padding: 5px 5px 6px; font: 11px "Lucida Grande", "Verdana"; border: 1px solid #999; } -form ul.holder { width: 500px; } -#facebook-list ul.holder li.bit-box, #apple-list ul.holder li.bit-box { padding-right: 15px; position: relative; } -#apple-list ul.holder li.bit-input { margin: 0; } -#apple-list ul.holder li.bit-input input.smallinput { width: 5px; } -ul.holder li.bit-hover { background: #BBCEF1; border: 1px solid #6D95E0; } -ul.holder li.bit-box-focus { border-color: #598BEC; background: #598BEC; color: #fff; } -ul.holder li.bit-box a.closebutton { position: absolute; right: 4px; top: 5px; display: block; width: 7px; height: 7px; font-size: 1px; background: url('images/close.gif'); } -ul.holder li.bit-box a.closebutton:hover { background-position: 7px; } -ul.holder li.bit-box-focus a.closebutton, ul.holder li.bit-box-focus a.closebutton:hover { background-position: bottom; } - -/* Autocompleter */ - -#facebook-auto { display: none; position: absolute; width: 512px; background: #eee; } -#facebook-auto .default { padding: 5px 7px; border: 1px solid #ccc; border-width: 0 1px 1px; } -#facebook-auto ul { display: none; margin: 0; padding: 0; overflow: auto; } -#facebook-auto ul li { padding: 5px 12px; z-index: 1000; cursor: pointer; margin: 0; list-style-type: none; border: 1px solid #ccc; border-width: 0 1px 1px; font: 11px "Lucida Grande", "Verdana"; } -#facebook-auto ul li em { font-weight: bold; font-style: normal; background: #ccc; } -#facebook-auto ul li.auto-focus { background: #4173CC; color: #fff; } -#facebook-auto ul li.auto-focus em { background: none; } - -#demo ul.holder li.bit-input input { padding: 2px 0 1px; border: 1px solid #999; } -#add a { color: #666; } -#add-test { width: 100px; padding: 2px; } -#button_container { margin-left: 70px; margin-bottom: 30px;} \ No newline at end of file diff --git a/e107_plugins/pm/test.js b/e107_plugins/pm/test.js deleted file mode 100644 index 041e994d3..000000000 --- a/e107_plugins/pm/test.js +++ /dev/null @@ -1,209 +0,0 @@ -/* - Proto!MultiSelect 0.2 - - Prototype version required: 6.0 - - Credits: - - Idea: Facebook - - Guillermo Rauch: Original MooTools script - - Ran Grushkowsky/InteRiders Inc. : Porting into Prototype and further development - - Changelog: - - 0.1: translation of MooTools script - - 0.2: renamed from Proto!TextboxList to Proto!MultiSelect, added new features/bug fixes - added feature: support to fetch list on-the-fly using AJAX Credit: Cheeseroll - added feature: support for value/caption - added feature: maximum results to display, when greater displays a scrollbar Credit: Marcel - added feature: filter by the beginning of word only or everywhere in the word Credit: Kiliman - added feature: shows hand cursor when going over options - bug fix: the click event stopped working - bug fix: the cursor does not 'travel' when going up/down the list Credit: Marcel -*/ - -/* Copyright: InteRiders - Distributed under MIT - Keep this message! */ - -var FacebookList = Class.create(TextboxList, { - - loptions: $H({ - autocomplete: { - 'opacity': 0.8, - 'maxresults': 10, - 'minchars': 1 - } - }), - - initialize: function($super,element, autoholder, options, func) { - $super(element, options); - this.data = []; - this.autoholder = $(autoholder).setOpacity(this.loptions.get('autocomplete').opacity); - this.autoholder.observe('mouseover',function() {this.curOn = true;}.bind(this)).observe('mouseout',function() {this.curOn = false;}.bind(this)); - this.autoresults = this.autoholder.select('ul').first(); - var children = this.autoresults.select('li'); - children.each(function(el) { this.add({value:el.readAttribute('value'),caption:el.innerHTML}); }, this); - }, - - autoShow: function(search) { - this.autoholder.setStyle({'display': 'block'}); - this.autoholder.descendants().each(function(e) { e.hide() }); - if(! search || ! search.strip() || (! search.length || search.length < this.loptions.get('autocomplete').minchars)) - { - this.autoholder.select('.default').first().setStyle({'display': 'block'}); - this.resultsshown = false; - } else { - this.resultsshown = true; - this.autoresults.setStyle({'display': 'block'}).update(''); - if (this.options.get('wordMatch')) - var regexp = new RegExp("(^|\\s)"+search,'i') - else - var regexp = new RegExp(search,'i') - var count = 0; - this.data.filter(function(str) { return str ? regexp.test(str.evalJSON(true).caption) : false; }).each(function(result, ti) { - count++; - if(ti >= this.loptions.get('autocomplete').maxresults) return; - var that = this; - var el = new Element('li'); - el.observe('click',function(e) { - e.stop(); - that.autoAdd(this); - }).observe('mouseover',function() { - that.autoFocus(this); - }).update(this.autoHighlight(result.evalJSON(true).caption, search)); - this.autoresults.insert(el); - el.cacheData('result', result.evalJSON(true)); - if(ti == 0) this.autoFocus(el); - }, this); - } - if (count > this.options.get('results')) - this.autoresults.setStyle({'height': (this.options.get('results')*24)+'px'}); - else - this.autoresults.setStyle({'height': (count?(count*24):0)+'px'}); - return this; - }, - - autoHighlight: function(html, highlight) { - return html.gsub(new RegExp(highlight,'i'), function(match) { - return '' + match[0] + ''; - }); - }, - - autoHide: function() { - this.resultsshown = false; - this.autoholder.hide(); - return this; - }, - - autoFocus: function(el) { - if(! el) return; - if(this.autocurrent) this.autocurrent.removeClassName('auto-focus'); - this.autocurrent = el.addClassName('auto-focus'); - return this; - }, - - autoMove: function(direction) { - if(!this.resultsshown) return; - this.autoFocus(this.autocurrent[(direction == 'up' ? 'previous' : 'next')]()); - this.autoresults.scrollTop = this.autocurrent.positionedOffset()[1]-this.autocurrent.getHeight(); - return this; - }, - - autoFeed: function(text) { - if (this.data.indexOf(Object.toJSON(text)) == -1) - this.data.push(Object.toJSON(text)); - return this; - }, - - autoAdd: function(el) { - if(!el || ! el.retrieveData('result')) return; - this.add(el.retrieveData('result')); - delete this.data[this.data.indexOf(Object.toJSON(el.retrieveData('result')))]; - this.autoHide(); - var input = this.lastinput || this.current.retrieveData('input'); - input.clear().focus(); - return this; - }, - - createInput: function($super,options) { - var li = $super(options); - var input = li.retrieveData('input'); - input.observe('keydown', function(e) { - this.dosearch = false; - switch(e.keyCode) { - case Event.KEY_UP: e.stop(); return this.autoMove('up'); - case Event.KEY_DOWN: e.stop(); return this.autoMove('down'); - case Event.KEY_RETURN: - e.stop(); - if(! this.autocurrent) break; - this.autoAdd(this.autocurrent); - this.autocurrent = false; - this.autoenter = true; - break; - case Event.KEY_ESC: - this.autoHide(); - if(this.current && this.current.retrieveData('input')) - this.current.retrieveData('input').clear(); - break; - default: this.dosearch = true; - } - }.bind(this)); - input.observe('keyup',function(e) { - - switch(e.keyCode) { - case Event.KEY_UP: - case Event.KEY_DOWN: - case Event.KEY_RETURN: - case Event.KEY_ESC: - break; - default: - if (!Object.isUndefined(this.options.get('fetchFile'))) { - new Ajax.Request(this.options.get('fetchFile'), { - parameters: {keyword: input.value}, - onSuccess: function(transport) { - transport.responseText.evalJSON(true).each(function(t){this.autoFeed(t)}.bind(this)); - this.autoShow(input.value); - }.bind(this) - }); - } - else - if(this.dosearch) this.autoShow(input.value); - } - }.bind(this)); - input.observe(Prototype.Browser.IE ? 'keydown' : 'keypress', function(e) { - if(this.autoenter) e.stop(); - this.autoenter = false; - }.bind(this)); - return li; - }, - - createBox: function($super,text, options) { - var li = $super(text, options); - li.observe('mouseover',function() { - this.addClassName('bit-hover'); - }).observe('mouseout',function() { - this.removeClassName('bit-hover') - }); - var a = new Element('a', { - 'href': '#', - 'class': 'closebutton' - } - ); - a.observe('click',function(e) { - e.stop(); - if(! this.current) this.focus(this.maininput); - this.dispose(li); - }.bind(this)); - li.insert(a).cacheData('text', Object.toJSON(text)); - return li; - } - -}); - -Element.addMethods({ - onBoxDispose: function(item,obj) { obj.autoFeed(item.retrieveData('text').evalJSON(true)); }, - onInputFocus: function(el,obj) { obj.autoShow(); }, - onInputBlur: function(el,obj) { - obj.lastinput = el; - if(!obj.curOn) { - obj.blurhide = obj.autoHide.bind(obj).delay(0.1); - } - }, - filter:function(D,E){var C=[];for(var B=0,A=this.length;B - - Guillermo Rauch: Original MooTools script - - Ran Grushkowsky/InteRiders Inc. : Porting into Prototype and further development - - Changelog: - - 0.1: translation of MooTools script - - 0.2: renamed from Proto!TextboxList to Proto!MultiSelect, added new features/bug fixes - added feature: support to fetch list on-the-fly using AJAX Credit: Cheeseroll - added feature: support for value/caption - added feature: maximum results to display, when greater displays a scrollbar Credit: Marcel - added feature: filter by the beginning of word only or everywhere in the word Credit: Kiliman - added feature: shows hand cursor when going over options - bug fix: the click event stopped working - bug fix: the cursor does not 'travel' when going up/down the list Credit: Marcel -*/ - -/* Copyright: InteRiders - Distributed under MIT - Keep this message! */ - -var ResizableTextbox = Class.create({ - - options: $H({ - min: 5, - max: 500, - step: 7 - }), - - initialize: function(element, options) { - var that = this; - this.options.update(options); - this.el = $(element); - this.width = this.el.offsetWidth; - this.el.observe( - 'keyup', function() { - var newsize = that.options.get('step') * $F(this).length; - if(newsize <= that.options.get('min')) newsize = that.width; - if(! ($F(this).length == this.retrieveData('rt-value') || newsize <= that.options.min || newsize >= that.options.max)) - this.setStyle({'width': newsize}); - }).observe('keydown', function() { - this.cacheData('rt-value', $F(this).length); - }); - } -}); - -var TextboxList = Class.create({ - - options: $H({/* - onFocus: $empty, - onBlur: $empty, - onInputFocus: $empty, - onInputBlur: $empty, - onBoxFocus: $empty, - onBoxBlur: $empty, - onBoxDispose: $empty,*/ - resizable: {}, - className: 'bit', - separator: '###', - extrainputs: true, - startinput: true, - hideempty: true, - fetchFile: undefined, - results: 10, - wordMatch: false - }), - - initialize: function(element, options) { - this.options.update(options); - this.element = $(element).hide(); - this.bits = new Hash(); - this.events = new Hash(); - this.count = 0; - this.current = false; - this.maininput = this.createInput({'class': 'maininput'}); - this.holder = new Element('ul', { - 'class': 'holder' - }).insert(this.maininput); - this.element.insert({'before':this.holder}); - this.holder.observe('click', function(event){ - event.stop(); - if(this.maininput != this.current) this.focus(this.maininput); - }.bind(this)); - this.makeResizable(this.maininput); - this.setEvents(); - }, - - setEvents: function() { - document.observe(Prototype.Browser.IE ? 'keydown' : 'keypress', function(e) { - if(! this.current) return; - if(this.current.retrieveData('type') == 'box' && e.keyCode == Event.KEY_BACKSPACE) e.stop(); - }.bind(this)); - - document.observe( - 'keyup', function(e) { - e.stop(); - if(! this.current) return; - switch(e.keyCode){ - case Event.KEY_LEFT: return this.move('left'); - case Event.KEY_RIGHT: return this.move('right'); - case Event.KEY_DELETE: - case Event.KEY_BACKSPACE: return this.moveDispose(); - } - }.bind(this)).observe( - 'click', function() { document.fire('blur'); }.bindAsEventListener(this) - ); - }, - - update: function() { - this.element.value = this.bits.values().join(this.options.get('separator')); - return this; - }, - - add: function(text, html) { - var id = this.options.get('className') + '-' + this.count++; - var el = this.createBox($pick(html, text), {'id': id}); - (this.current || this.maininput).insert({'before':el}); - el.observe('click', function(e) { - e.stop(); - this.focus(el); - }.bind(this)); - this.bits.set(id, text.value); - if(this.options.get('extrainputs') && (this.options.get('startinput') || el.previous())) this.addSmallInput(el,'before'); - return el; - }, - - addSmallInput: function(el, where) { - var input = this.createInput({'class': 'smallinput'}); - el.insert({}[where] = input); - input.cacheData('small', true); - this.makeResizable(input); - if(this.options.get('hideempty')) input.hide(); - return input; - }, - - dispose: function(el) { - this.bits.unset(el.id); - if(el.previous() && el.previous().retrieveData('small')) el.previous().remove(); - if(this.current == el) this.focus(el.next()); - if(el.retrieveData('type') == 'box') el.onBoxDispose(this); - el.remove(); - return this; - }, - - focus: function(el, nofocus) { - if(! this.current) el.fire('focus'); - else if(this.current == el) return this; - this.blur(); - el.addClassName(this.options.get('className') + '-' + el.retrieveData('type') + '-focus'); - if(el.retrieveData('small')) el.setStyle({'display': 'block'}); - if(el.retrieveData('type') == 'input') { - el.onInputFocus(this); - if(! nofocus) this.callEvent(el.retrieveData('input'), 'focus'); - } - else el.fire('onBoxFocus'); - this.current = el; - return this; - }, - - blur: function(noblur) { - if(! this.current) return this; - if(this.current.retrieveData('type') == 'input') { - var input = this.current.retrieveData('input'); - if(! noblur) this.callEvent(input, 'blur'); - input.onInputBlur(this); - } - else this.current.fire('onBoxBlur'); - if(this.current.retrieveData('small') && ! input.get('value') && this.options.get('hideempty')) - this.current.hide(); - this.current.removeClassName(this.options.get('className') + '-' + this.current.retrieveData('type') + '-focus'); - this.current = false; - return this; - }, - - createBox: function(text, options) { - return new Element('li', options).addClassName(this.options.get('className') + '-box').update(text.caption).cacheData('type', 'box'); - }, - - createInput: function(options) { - var li = new Element('li', {'class': this.options.get('className') + '-input'}); - var el = new Element('input', Object.extend(options,{'type': 'text'})); - el.observe('click', function(e) { e.stop(); }).observe('focus', function(e) { if(! this.isSelfEvent('focus')) this.focus(li, true); }.bind(this)).observe('blur', function() { if(! this.isSelfEvent('blur')) this.blur(true); }.bind(this)).observe('keydown', function(e) { this.cacheData('lastvalue', this.value).cacheData('lastcaret', this.getCaretPosition()); }); - var tmp = li.cacheData('type', 'input').cacheData('input', el).insert(el); - return tmp; - }, - - callEvent: function(el, type) { - this.events.set(type, el); - el[type](); - }, - - isSelfEvent: function(type) { - return (this.events.get(type)) ? !! this.events.unset(type) : false; - }, - - makeResizable: function(li) { - var el = li.retrieveData('input'); - el.cacheData('resizable', new ResizableTextbox(el, Object.extend(this.options.get('resizable'),{min: el.offsetWidth, max: (this.element.getWidth()?this.element.getWidth():0)}))); - return this; - }, - - checkInput: function() { - var input = this.current.retrieveData('input'); - return (! input.retrieveData('lastvalue') || (input.getCaretPosition() === 0 && input.retrieveData('lastcaret') === 0)); - }, - - move: function(direction) { - var el = this.current[(direction == 'left' ? 'previous' : 'next')](); - if(el && (! this.current.retrieveData('input') || ((this.checkInput() || direction == 'right')))) this.focus(el); - return this; - }, - - moveDispose: function() { - if(this.current.retrieveData('type') == 'box') return this.dispose(this.current); - if(this.checkInput() && this.bits.keys().length && this.current.previous()) return this.focus(this.current.previous()); - } - -}); - -//helper functions -Element.addMethods({ - getCaretPosition: function() { - if (this.createTextRange) { - var r = document.selection.createRange().duplicate(); - r.moveEnd('character', this.value.length); - if (r.text === '') return this.value.length; - return this.value.lastIndexOf(r.text); - } else return this.selectionStart; - }, - cacheData: function(element, key, value) { - if (Object.isUndefined(this[$(element).identify()]) || !Object.isHash(this[$(element).identify()])) - this[$(element).identify()] = $H(); - this[$(element).identify()].set(key,value); - return element; - }, - retrieveData: function(element,key) { - return this[$(element).identify()].get(key); - } -}); - -function $pick(){for(var B=0,A=arguments.length;B array( - 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used - 'legacy' => '{e_PLUGIN}pm/pm.php', // this config won't work in single entry point mod (legacy not used at all), so just set this to default plugin file to notify router it's legacy module - 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating - 'defaultRoute' => 'view/inbox', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - ), - - // rule set array - 'rules' => array() - ); - - } - - /** - * Describe all pm routes. - * Routes vs legacy queries: - * view/inbox -> ?inbox (default route, resolved on index/index) - * view/outbox -> ?outbox - * view/message?id=xxx -> ?show.xxx.inbox - * view/sent?id=xxx -> ?show.xxx.outbox - * view/show?id=xxx -> ?show.xxx (investigate why we have dupps, good time to remove them!) - * view/reply?id=xxx -> ?reply.xxx - * view/send -> ?send - * action/delete-in?id=xx -> ?del.xxx.inbox - * action/delete-out?id=xx -> ?del.xxx.outbox - * action/delete-blocked?id=xxx -> ?delblocked.xxx - * action/block?id=xx -> ?block.xxx - * action/unblock?id=xx -> ?unblock.xxx - * action/get?id=xxx&index=yyy -> ?get.xxx.yyy - */ - public function create($route, $params = array(), $options = array()) - { - if(is_string($route)) $route = explode('/', $route, 2); - if(!varset($route[0]) || 'index' == $route[0]) $route[0] = 'view'; - if(!varset($route[1])) $route[1] = 'inbox'; - $base = e107::getInstance()->getFolder('plugins').'pm/'; - - //var_dump($options, $route, $params); - if($route[0] == 'view') - { - if(!isset($params['id']) && isset($params['pm_id'])) $params['id'] = $params['pm_id']; - switch($route[1]) - { - case 'index': - case 'inbox': - $this->legacyQueryString = 'inbox'; - return $base.'pm.php?inbox'; - break; - - case 'outbox': - $this->legacyQueryString = 'outbox'; - return $base.'pm.php?outbox'; - break; - - // we could just remove them all and let only 'message' live - case 'show': - $this->legacyQueryString = 'show.'.$params['id']; - return $base.'pm.php?show.'.$params['id']; - break; - - case 'message': - $this->legacyQueryString = 'show.'.$params['id'].'.inbox'; - return $base.'pm.php?show.'.$params['id'].'.inbox'; - break; - - case 'sent': - $this->legacyQueryString = 'show.'.$params['id'].'.outbox'; - return $base.'pm.php?show.'.$params['id'].'.outbox'; - break; - - case 'reply': - $this->legacyQueryString = 'reply.'.$params['id']; - return $base.'pm.php?reply.'.$params['id']; - break; - - case 'new': - $this->legacyQueryString = 'send'; - return $base.'pm.php?send'; - break; - } - } - elseif($route[0] == 'action') - { - if(!isset($params['id']) && isset($params['pm_id'])) $params['id'] = $params['pm_id']; - switch($route[1]) - { - case 'delete-in': - $this->legacyQueryString = 'del.'.$params['id'].'.inbox'; - return $base.'pm.php?del.'.$params['id'].'.inbox'; - break; - - case 'delete-out': - $this->legacyQueryString = 'del.'.$params['id'].'.outbox'; - return $base.'pm.php?del.'.$params['id'].'.outbox'; - break; - - case 'delete-blocked': - $this->legacyQueryString = 'delblocked.'.$params['id']; - return $base.'pm.php?delblocked.'.$params['id']; - break; - - case 'block': - $this->legacyQueryString = 'block.'.$params['id']; - return $base.'pm.php?block.'.$params['id']; - break; - - case 'unblock': - $this->legacyQueryString = 'unblock.'.$params['id']; - return $base.'pm.php?unblock.'.$params['id']; - break; - - case 'get': - $this->legacyQueryString = 'get.'.$params['id'].'.'.$params['index']; - return $base.'pm.php?get.'.$params['id'].'.'.$params['index']; - break; - } - } - - return false; - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - e107::plugLan('pm', 'admin_pm', true); - static $admin = array( - 'labels' => array( - 'name' => LAN_PLUGIN_PM_NAME, // Module name - 'label' => LAN_PLUGIN_PM_URL_DEFAULT_LABEL, // Current profile name - 'description' => LAN_PLUGIN_PM_URL_DEFAULT_DESCR, // - 'examples' => array("{e_PLUGIN_ABS}pm/pm.php") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} diff --git a/e107_themes/bootstrap3/theme_shortcodes.php b/e107_themes/bootstrap3/theme_shortcodes.php index 992b2f07c..a584aa8ae 100644 --- a/e107_themes/bootstrap3/theme_shortcodes.php +++ b/e107_themes/bootstrap3/theme_shortcodes.php @@ -88,7 +88,7 @@ class theme_shortcodes extends e_shortcode { $text = '