diff --git a/include/class.client.php b/include/class.client.php index 2d157ede502923d5e88fcbfa90f79924346c30b7..2d1f2930c12b2cc8201fc8313b54656836625fac 100644 --- a/include/class.client.php +++ b/include/class.client.php @@ -457,7 +457,6 @@ class ClientAccount extends UserAccount { if ($errors) return false; $this->set('timezone', $vars['timezone']); - $this->set('dst', isset($vars['dst']) ? 1 : 0); // Change language $this->set('lang', $vars['lang'] ?: null); Internationalization::setCurrentLanguage(null); diff --git a/include/class.filter.php b/include/class.filter.php index f9c32d5cd363e14f64ef5be13c75a65a347bc18b..2170f412bc90cd3d4cc1b2f817f839465cc338ea 100755 --- a/include/class.filter.php +++ b/include/class.filter.php @@ -133,16 +133,21 @@ extends VerySimpleModel { } public function setFlag($flag, $val) { + $vars = array(); $errors = array(); if ($val) $this->flags |= $flag; else - $this->ht['flags'] &= ~$flag; + $this->flags &= ~$flag; $vars['rules']= $this->getRules(); $this->ht['pass'] = true; $this->update($this->ht, $errors); } + function hasFlag($flag) { + return 0 !== ($this->ht['flags'] & $flag); + } + function stopOnMatch() { return ($this->stop_onmatch); } @@ -325,8 +330,6 @@ extends VerySimpleModel { if (!self::validate_actions($vars, $errors)) return false; - $vars['flags'] = $this->flags; - if(!$vars['execorder']) $errors['execorder'] = __('Order required'); elseif(!is_numeric($vars['execorder'])) @@ -354,6 +357,9 @@ extends VerySimpleModel { $vars['target'] = 'Email'; } + //Note: this will be set when validating filters + if ($vars['email_id']) + $emailId = $vars['email_id']; $this->isactive = $vars['isactive']; $this->flags = $vars['flags']; $this->target = $vars['target']; @@ -420,38 +426,45 @@ extends VerySimpleModel { $types = array_keys(self::getSupportedMatchTypes()); $rules = array(); foreach ($vars['rules'] as $i=>$rule) { + if ($rule->ht) { + $rule = $rule->ht; + $rule["w"] = $rule["what"]; + $rule["h"] = $rule["how"]; + $rule["v"] = $rule["val"]; + } + if (is_array($rule)) { if($rule["w"] || $rule["h"]) { - // Check for REGEX compile errors - if (in_array($rule["h"], array('match','not_match'))) { - $wrapped = "/".$rule["v"]."/iu"; - if (false === @preg_match($rule["v"], ' ') - && (false !== @preg_match($wrapped, ' '))) - $rule["v"] = $wrapped; - } - - if(!$rule["w"] || !in_array($rule["w"],$matches)) - $errors["rule_$i"]=__('Invalid match selection'); - elseif(!$rule["h"] || !in_array($rule["h"],$types)) - $errors["rule_$i"]=__('Invalid match type selection'); - elseif(!$rule["v"]) - $errors["rule_$i"]=__('Value required'); - elseif($rule["w"]=='email' - && $rule["h"]=='equal' - && !Validator::is_email($rule["v"])) - $errors["rule_$i"]=__('Valid email required for the match type'); - elseif (in_array($rule["h"], array('match','not_match')) - && (false === @preg_match($rule["v"], ' '))) - $errors["rule_$i"] = sprintf(__('Regex compile error: (#%s)'), - preg_last_error()); - - - else //for everything-else...we assume it's valid. - $rules[]=array('what'=>$rule["w"], - 'how'=>$rule["h"],'val'=>trim($rule["v"])); - }elseif($rule["v"]) { - $errors["rule_$i"]=__('Incomplete selection'); + // Check for REGEX compile errors + if (in_array($rule["h"], array('match','not_match'))) { + $wrapped = "/".$rule["v"]."/iu"; + if (false === @preg_match($rule["v"], ' ') + && (false !== @preg_match($wrapped, ' '))) + $rule["v"] = $wrapped; } + + if(!$rule["w"] || !in_array($rule["w"],$matches)) + $errors["rule_$i"]=__('Invalid match selection'); + elseif(!$rule["h"] || !in_array($rule["h"],$types)) + $errors["rule_$i"]=__('Invalid match type selection'); + elseif(!$rule["v"]) + $errors["rule_$i"]=__('Value required'); + elseif($rule["w"]=='email' + && $rule["h"]=='equal' + && !Validator::is_email($rule["v"])) + $errors["rule_$i"]=__('Valid email required for the match type'); + elseif (in_array($rule["h"], array('match','not_match')) + && (false === @preg_match($rule["v"], ' '))) + $errors["rule_$i"] = sprintf(__('Regex compile error: (#%s)'), + preg_last_error()); + + + else //for everything-else...we assume it's valid. + $rules[]=array('what'=>$rule["w"], + 'how'=>$rule["h"],'val'=>trim($rule["v"])); + }elseif($rule["v"]) { + $errors["rule_$i"]=__('Incomplete selection'); + } } } @@ -483,7 +496,6 @@ extends VerySimpleModel { function save($refetch=false) { if ($this->dirty) $this->updated = SqlFunction::NOW(); - return parent::save($refetch || $this->dirty); } diff --git a/include/class.filter_action.php b/include/class.filter_action.php index 69117e2041b7e45ec09d017b435a016adda28e08..2a7caf468dacc32cfb6018d1df80ed94e673d48b 100644 --- a/include/class.filter_action.php +++ b/include/class.filter_action.php @@ -87,10 +87,10 @@ class FilterAction extends VerySimpleModel { function setFilterFlag($actions, $flag, $bool) { foreach ($actions as $action) { $filter = Filter::lookup($action->filter_id); - if ($filter) { - if ($flag == 'dept') $filter->setFlag(Filter::FLAG_INACTIVE_DEPT, $bool); - if ($flag == 'topic') $filter->setFlag(Filter::FLAG_INACTIVE_HT, $bool); - } + if ($filter && ($flag == 'dept') && ($filter->hasFlag(Filter::FLAG_INACTIVE_DEPT) != $bool)) + $filter->setFlag(Filter::FLAG_INACTIVE_DEPT, $bool); + if ($filter && ($flag == 'topic') && ($filter->hasFlag(Filter::FLAG_INACTIVE_HT) != $bool)) + $filter->setFlag(Filter::FLAG_INACTIVE_HT, $bool); } } diff --git a/include/class.forms.php b/include/class.forms.php index d199d22a64e07a7cb97b562139d8aab2317286df..d2add77de539b0f3dd1fcd27abee8800c15119fd 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -1478,6 +1478,10 @@ class TextboxField extends FormField { function parse($value) { return Format::striptags($value); } + + function display($value) { + return ($value == '0') ? '0' : Format::htmlchars($this->toString($value ?: $this->value)); + } } class PasswordField extends TextboxField { diff --git a/include/class.pdf.php b/include/class.pdf.php index 6d3a6553b111983ab69db7a84fadeba5729beb0a..bb8432ab40de66e2b9a580d895b590c02c4362a5 100644 --- a/include/class.pdf.php +++ b/include/class.pdf.php @@ -67,7 +67,7 @@ class Ticket2PDF extends mPDFWithLocalImages $this->ticket = $ticket; $this->includenotes = $notes; - parent::__construct(['mode' => 'utf-8', 'format' => $psize, 'tempDir'=>INCLUDE_DIR.'mpdf/ttfontdata']); + parent::__construct(['mode' => 'utf-8', 'format' => $psize, 'tempDir'=>sys_get_temp_dir()]); $this->_print(); } diff --git a/include/class.queue.php b/include/class.queue.php index a7b84f47fe8a25589acf1b7b2bcb688e1abd40e6..9a0ad18620417d0c17c45d71c524031971c80d1e 100644 --- a/include/class.queue.php +++ b/include/class.queue.php @@ -1141,9 +1141,6 @@ class CustomQueue extends VerySimpleModel { return false; $order = array_keys($fields); - // Filter exportable fields - if (!($fields = array_intersect_key($this->getExportableFields(), $fields))) - return false; $new = $fields; foreach ($this->exports as $f) { diff --git a/include/class.staff.php b/include/class.staff.php index c02bdb342b525f9ff851b7b9bd70c4e2052d8f70..9f346df4e58dfc4189571e6d4444858a2b753b88 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -91,6 +91,7 @@ implements AuthenticatedUser, EmailContact, TemplateVariable, Searchable { 'datetime_format' => '', 'thread_view_order' => '', 'default_ticket_queue_id' => 0, + 'reply_redirect' => 'Ticket', )); $this->_config = $_config->getInfo(); } @@ -347,6 +348,10 @@ implements AuthenticatedUser, EmailContact, TemplateVariable, Searchable { return $this->default_paper_size; } + function getReplyRedirect() { + return $this->reply_redirect; + } + function forcePasswdChange() { return $this->change_passwd; } @@ -744,6 +749,7 @@ implements AuthenticatedUser, EmailContact, TemplateVariable, Searchable { 'default_from_name' => $vars['default_from_name'], 'thread_view_order' => $vars['thread_view_order'], 'default_ticket_queue_id' => $vars['default_ticket_queue_id'], + 'reply_redirect' => ($vars['reply_redirect'] == 'Queue') ? 'Queue' : 'Ticket', ) ); $this->_config = $_config->getInfo(); diff --git a/include/class.task.php b/include/class.task.php index 55f0152896da820a1897076c884596659bc462e4..fe1e71921766846433ec0e245adcc2ce1ae7690a 100644 --- a/include/class.task.php +++ b/include/class.task.php @@ -1189,7 +1189,7 @@ class Task extends TaskModel implements RestrictedAccess, Threadable { global $cfg; if (!$entry instanceof ThreadEntry - || !($recipients=$this->getThread()->getParticipants()) + || !($recipients=$this->getThread()->getRecipients()) || !($dept=$this->getDept()) || !($tpl=$dept->getTemplate()) || !($msg=$tpl->getTaskActivityNoticeMsgTemplate()) diff --git a/include/class.thread.php b/include/class.thread.php index 343b3e9005689e01a11ef5611e3a00179b776f82..a9485d0b85477e339e6d4fc3cbe4ae978a15abb6 100644 --- a/include/class.thread.php +++ b/include/class.thread.php @@ -263,6 +263,17 @@ implements Searchable { return $this->_participants; } + // MailingList of recipients (collaborators) + function getRecipients() { + $list = new MailingList(); + if ($collabs = $this->getActiveCollaborators()) { + foreach ($collabs as $c) + $list->addCc($c); + } + + return $list; + } + function getReferral($id, $type) { return $this->referrals->findFirst(array( diff --git a/include/class.util.php b/include/class.util.php index a3bc2305d130c8b7bf5885cc4df99f4dcf1cae22..e78c00d1d56347ccacdc1c0ca0702bc91ea65ba1 100644 --- a/include/class.util.php +++ b/include/class.util.php @@ -5,6 +5,7 @@ require_once INCLUDE_DIR . 'class.variable.php'; // Used by the email system interface EmailContact { function getId(); + function getUserId(); function getName(); function getEmail(); } @@ -28,6 +29,10 @@ implements EmailContact { return $this->contact->getId(); } + function getUserId() { + return $this->contact->getUserId(); + } + function getEmail() { return $this->contact->getEmail(); } diff --git a/include/staff/dashboard.inc.php b/include/staff/dashboard.inc.php index 3c91e3c5fd9135cb550a2c39de52c4a0411445db..c921b2b40964040ac66147f21114e7155e8b1b31 100644 --- a/include/staff/dashboard.inc.php +++ b/include/staff/dashboard.inc.php @@ -180,4 +180,16 @@ foreach ($groups as $g=>$desc) { </form> <script> $.drawPlots(<?php echo JsonDataEncoder::encode($report->getPlotData()); ?>); + // Set Selected Period For Dashboard Stats and Export + <?php if ($report && $report->end) { ?> + $("div#basic_search select option").each(function(){ + // Remove default selection + if ($(this)[0].selected) + $(this).removeAttr('selected'); + // Set the selected period by the option's value (periods equal + // option's values) + if ($(this).val() == "<?php echo $report->end; ?>") + $(this).attr("selected","selected"); + }); + <?php } ?> </script> diff --git a/include/staff/profile.inc.php b/include/staff/profile.inc.php index a8a4a2a56d73e51d6206503dfbbc0aaa7a8c9191..8e72ffc43c6638b3a52505f20679a80d16a061d0 100644 --- a/include/staff/profile.inc.php +++ b/include/staff/profile.inc.php @@ -300,6 +300,23 @@ if ($avatar->isChangeable()) { ?> <div class="error"><?php echo $errors['default_paper_size']; ?></div> </td> </tr> + <tr> + <td><?php echo __('Reply Redirect'); ?>: + <div class="faded"><?php echo __('Redirect URL used after replying to a ticket.');?></div> + </td> + <td> + <select name="reply_redirect"> + <?php + $options=array('Queue'=>__('Queue'),'Ticket'=>__('Ticket')); + foreach($options as $key=>$opt) { + echo sprintf('<option value="%s" %s>%s</option>', + $key,($staff->reply_redirect==$key)?'selected="selected"':'',$opt); + } + ?> + </select> + <div class="error"><?php echo $errors['reply_redirect']; ?></div> + </td> + </tr> </tbody> <tbody> <tr class="header"> diff --git a/include/staff/templates/collaborators.tmpl.php b/include/staff/templates/collaborators.tmpl.php index d25d10a83fb72bd3c84797137503ac74d89f8f9c..b2545daa315c3f889f1150267c8736eccea54401 100644 --- a/include/staff/templates/collaborators.tmpl.php +++ b/include/staff/templates/collaborators.tmpl.php @@ -81,10 +81,10 @@ if(($users=$thread->getCollaborators())) {?> if ($_POST && $thread && $thread->getNumCollaborators()) { - $collaborators = sprintf('Participants (%d)', + $collaborators = sprintf('Collaborators (%d)', $thread->getNumCollaborators()); - $recipients = sprintf(__('Recipients (%d of %d)'), + $recipients = sprintf(__('Collaborators (%d of %d)'), $thread->getNumActiveCollaborators(), $thread->getNumCollaborators()); ?> diff --git a/include/staff/templates/queue-quickfilter.tmpl.php b/include/staff/templates/queue-quickfilter.tmpl.php index 9e4d64850a5ec3ea3e7afac9d17e179c62edd7de..d7919963d54237f9e12186e217b0905c379cccc4 100644 --- a/include/staff/templates/queue-quickfilter.tmpl.php +++ b/include/staff/templates/queue-quickfilter.tmpl.php @@ -36,7 +36,7 @@ $.pjax({ url: '?' + query, timeout: 2000, container: '#pjax-container'});"> - <ul> + <ul <?php if (count($choices) > 20) echo 'style="height:500px;overflow-x:hidden;overflow-y:scroll;"'; ?>> <?php foreach ($choices as $k=>$desc) { $selected = isset($quick_filter) && $quick_filter == $k; ?> diff --git a/include/staff/templates/queue-tickets.tmpl.php b/include/staff/templates/queue-tickets.tmpl.php index 699b28a351e98f547528d3ea2cbd9936603da4cf..dba05dea8c7278d6e9dbeb01af4af0e589bba1e8 100644 --- a/include/staff/templates/queue-tickets.tmpl.php +++ b/include/staff/templates/queue-tickets.tmpl.php @@ -76,6 +76,23 @@ if (!$sorted && isset($sort['queuesort'])) { $page = ($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1; $pageNav = new Pagenate(PHP_INT_MAX, $page, PAGE_LIMIT); $tickets = $pageNav->paginateSimple($tickets); + +if (isset($tickets->extra['tables'])) { + // Creative twist here. Create a new query copying the query criteria, sort, limit, + // and offset. Then join this new query to the $tickets query and clear the + // criteria, sort, limit, and offset from the outer query. + $criteria = clone $tickets; + $criteria->limit(500); + $criteria->annotations = $criteria->related = $criteria->aggregated = + $criteria->annotations = $criteria->ordering = []; + $tickets->constraints = $tickets->extra = []; + $tickets = $tickets->filter(['ticket_id__in' => + $criteria->values_flat('ticket_id')]); + # Index hint should be used on the $criteria query only + $tickets->clearOption(QuerySet::OPT_INDEX_HINT); + $tickets->distinct('ticket_id'); +} + $count = $queue->getCount($thisstaff) ?: (PAGE_LIMIT*3); $pageNav->setTotal($count, true); $pageNav->setURL('tickets.php', $args); diff --git a/include/staff/templates/task-view.tmpl.php b/include/staff/templates/task-view.tmpl.php index 6153c8f20da3987fecebbdedd08ed20783dd9faa..d56b230c2e96f26cb789b4a954ea3ee41777715a 100644 --- a/include/staff/templates/task-view.tmpl.php +++ b/include/staff/templates/task-view.tmpl.php @@ -146,7 +146,7 @@ if ($task->isOverdue()) <ul> <?php - if ($task->isOpen()) { ?> + if (!$task->isOpen()) { ?> <li> <a class="no-pjax task-action" href="#tasks/<?php echo $task->getId(); ?>/reopen"><i @@ -372,9 +372,9 @@ if (!$ticket) { ?> <th><?php echo __('Collaborators');?>:</th> <td> <?php - $collaborators = __('Add Participants'); + $collaborators = __('Collaborators'); if ($task->getThread()->getNumCollaborators()) - $collaborators = sprintf(__('Participants (%d)'), + $collaborators = sprintf(__('Collaborators (%d)'), $task->getThread()->getNumCollaborators()); echo sprintf('<span><a class="collaborators preview" @@ -486,9 +486,9 @@ else style="display:<?php echo $thread->getNumCollaborators() ? 'inline-block': 'none'; ?>;" > <?php - $recipients = __('Add Participants'); + $recipients = __('Collaborators'); if ($thread->getNumCollaborators()) - $recipients = sprintf(__('Recipients (%d of %d)'), + $recipients = sprintf(__('Collaborators (%d of %d)'), $thread->getNumActiveCollaborators(), $thread->getNumCollaborators()); @@ -664,7 +664,10 @@ $(function() { .slideUp(); } }) - .done(function() { }) + .done(function() { + $('#loading').hide(); + $.toggleOverlay(false); + }) .fail(function() { }); }); <?php diff --git a/include/staff/templates/tasks-actions.tmpl.php b/include/staff/templates/tasks-actions.tmpl.php index dc59eae4fc5827a7231c39dbdbb4a7fc2f9c0d2e..e323e30602aee51bd9bd7efe14a3879610a163a5 100644 --- a/include/staff/templates/tasks-actions.tmpl.php +++ b/include/staff/templates/tasks-actions.tmpl.php @@ -7,57 +7,23 @@ if ($agent->hasPerm(Task::PERM_CLOSE, false)) { if (isset($options['status'])) { $status = $options['status']; - ?> - <span - class="action-button" - data-dropdown="#action-dropdown-tasks-status"> - <i class="icon-caret-down pull-right"></i> - <a class="tasks-status-action" - href="#statuses" - data-placement="bottom" - data-toggle="tooltip" - title="<?php echo __('Change Status'); ?>"><i - class="icon-flag"></i></a> - </span> - <div id="action-dropdown-tasks-status" - class="action-dropdown anchor-right"> - <ul> - <?php - if (!$status || !strcasecmp($status, 'closed')) { ?> - <li> - <a class="no-pjax tasks-action" - href="#tasks/mass/reopen"><i - class="icon-fixed-width icon-undo"></i> <?php - echo __('Reopen');?> </a> - </li> - <?php - } - if (!$status || !strcasecmp($status, 'open')) { - ?> - <li> - <a class="no-pjax tasks-action" - href="#tasks/mass/close"><i - class="icon-fixed-width icon-ok-circle"></i> <?php - echo __('Close');?> </a> - </li> - <?php - } ?> - </ul> - </div> -<?php - } else { - $actions += array( - 'reopen' => array( - 'icon' => 'icon-undo', - 'action' => __('Reopen') - )); + if (strpos($status, 'closed') !== false) { + $actions += array( + 'reopen' => array( + 'icon' => 'icon-undo', + 'action' => __('Reopen') + )); + } - $actions += array( - 'close' => array( - 'icon' => 'icon-ok-circle', - 'action' => __('Close') - )); + + if (strpos($status, 'open') !== false) { + $actions += array( + 'close' => array( + 'icon' => 'icon-ok-circle', + 'action' => __('Close') + )); + } } } @@ -95,7 +61,7 @@ if ($agent->hasPerm(Task::PERM_DELETE, false)) { 'action' => __('Delete') )); } -if ($actions && !isset($options['status'])) { +if ($actions && isset($options['status'])) { $more = $options['morelabel'] ?: __('More'); ?> <span diff --git a/include/staff/ticket-tasks.inc.php b/include/staff/ticket-tasks.inc.php index ec19431ac78f1bd772377e31212e1d31be32bab0..8c0bc5db4ac54a322cd0d288efdef2d31a713f8f 100644 --- a/include/staff/ticket-tasks.inc.php +++ b/include/staff/ticket-tasks.inc.php @@ -40,12 +40,17 @@ $showing = $pageNav->showing().' '._N('task', 'tasks', $count); print __('Add New Task'); ?></a> <?php } + foreach ($tasks as $task) + $taskStatus .= $task->isOpen() ? 'open' : 'closed'; + if ($count) Task::getAgentActions($thisstaff, array( 'container' => '#tasks_content', 'callback_url' => sprintf('ajax.php/tickets/%d/tasks', $ticket->getId()), - 'morelabel' => __('Options'))); + 'morelabel' => __('Options'), + 'status' => $taskStatus ? $taskStatus : '') + ); ?> </div> <div class="clear"></div> diff --git a/scp/filters.php b/scp/filters.php index d3c8a1deec12597f4d5b540d9c36a578f69bb1dc..00e6d8da70a563f4b99da9634f96ba95e35f9a31 100644 --- a/scp/filters.php +++ b/scp/filters.php @@ -31,8 +31,6 @@ if($_POST){ if(!$filter){ $errors['err']=sprintf(__('%s: Unknown or invalid'), __('ticket filter')); }elseif($filter->update($_POST,$errors)){ - $filter->setFlag(Filter::FLAG_INACTIVE_DEPT, false); - $filter->setFlag(Filter::FLAG_INACTIVE_HT, false); $msg=sprintf(__('Successfully updated %s.'), __('this ticket filter')); }elseif(!$errors['err']){ $errors['err']=sprintf('%s %s', diff --git a/scp/login.php b/scp/login.php index 6e1854456c5757f4fdab2b3289728b3cc24a34fc..4853f7e31f028cd84f31cca74ddc833631a4d105 100644 --- a/scp/login.php +++ b/scp/login.php @@ -64,6 +64,8 @@ if ($_POST) { $redirect($_SERVER['REQUEST_URI']); } +} +if ($_POST && isset($_POST['userid'])) { // Lookup support backends for this staff $username = trim($_POST['userid']); if ($user = StaffAuthenticationBackend::process($username, @@ -94,8 +96,11 @@ elseif ($_GET['do']) { // Consider single sign-on authentication backends elseif (!$thisstaff || !($thisstaff->getId() || $thisstaff->isValid())) { if (($user = StaffAuthenticationBackend::processSignOn($errors, false)) - && ($user instanceof StaffSession)) - Http::redirect($dest); + && ($user instanceof StaffSession)) { + Http::redirect($dest); + } else if (isset($_SESSION['_staff']['auth']['msg'])) { + $msg = $_SESSION['_staff']['auth']['msg']; + } } // Browsers shouldn't suggest saving that username/password diff --git a/scp/tickets.php b/scp/tickets.php index 8881874e897217bbea32e02ba8735e482ee937ab..27179c0befe768bcfbfea7654772b45d16b12b3e 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -214,7 +214,7 @@ if($_POST && !$errors): $ticket = null; $redirect = 'tickets.php'; - if ($ticket) + if ($ticket && $thisstaff->getReplyRedirect() == 'Ticket') $redirect = 'tickets.php?id='.$ticket->getId(); } elseif (!$errors['err']) { diff --git a/setup/inc/class.installer.php b/setup/inc/class.installer.php index d5aff5044cbf99b2a8b6460b6251b215c4bc2911..defde3e8d0db26f992e8add2bbbed1bba3b8bc51 100644 --- a/setup/inc/class.installer.php +++ b/setup/inc/class.installer.php @@ -116,6 +116,8 @@ class Installer extends SetupWizard { /*************** We're ready to install ************************/ define('ADMIN_EMAIL',$vars['admin_email']); //Needed to report SQL errors during install. define('TABLE_PREFIX',$vars['prefix']); //Table prefix + if (!defined('SECRET_SALT')) + define('SECRET_SALT',md5(TABLE_PREFIX.ADMIN_EMAIL)); Bootstrap::defineTables(TABLE_PREFIX); Bootstrap::loadCode();