diff --git a/include/class.orm.php b/include/class.orm.php index 473be838ceba796105db5770b71d1f620f895f5e..72b34c81c598e59061005cb7c9af65bb2bc8d8a9 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -333,6 +333,11 @@ class VerySimpleModel { return static::getMeta()->newInstance($row); } + function __wakeup() { + // If a model is stashed in a session, refresh the model from the database + $this->refetch(); + } + function get($field, $default=false) { if (array_key_exists($field, $this->ht)) return $this->ht[$field]; @@ -1142,6 +1147,7 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl const OPT_NOSORT = 'nosort'; const OPT_NOCACHE = 'nocache'; const OPT_MYSQL_FOUND_ROWS = 'found_rows'; + const OPT_INDEX_HINT = 'indexhint'; const ITER_MODELS = 1; const ITER_HASH = 2; @@ -1477,6 +1483,14 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl return isset($this->options[$option]); } + function getOption($option) { + return @$this->options[$option] ?: false; + } + + function setOption($option, $value) { + $this->options[$option] = $value; + } + function countSelectFields() { $count = count($this->values) + count($this->annotations); if (isset($this->extra['select'])) @@ -3083,12 +3097,15 @@ class MySqlCompiler extends SqlCompiler { $group_by = $group_by ? ' GROUP BY '.implode(', ', $group_by) : ''; $joins = $this->getJoins($queryset); + if ($hint = $queryset->getOption(QuerySet::OPT_INDEX_HINT)) { + $hint = " USE INDEX ({$hint})"; + } $sql = 'SELECT '; if ($queryset->hasOption(QuerySet::OPT_MYSQL_FOUND_ROWS)) $sql .= 'SQL_CALC_FOUND_ROWS '; $sql .= implode(', ', $fields).' FROM ' - .$table.$joins.$where.$group_by.$having.$sort; + .$table.$hint.$joins.$where.$group_by.$having.$sort; // UNIONS if ($queryset->chain) { // If the main query is sorted, it will need parentheses diff --git a/include/class.queue.php b/include/class.queue.php index 643fdb712ec85742509ae87b575beb85a2276cc8..dca04826372a24917186f3c6fecec8ab3d21aaf6 100644 --- a/include/class.queue.php +++ b/include/class.queue.php @@ -2716,6 +2716,7 @@ extends VerySimpleModel { ); var $_columns; + var $_extra; function getRoot($hint=false) { switch ($hint ?: $this->root) { @@ -2733,6 +2734,12 @@ extends VerySimpleModel { return $this->id; } + function getExtra() { + if (isset($this->extra) && !isset($this->_extra)) + $this->_extra = JsonDataParser::decode($this->extra); + return $this->_extra; + } + function applySort(QuerySet $query, $reverse=false, $root=false) { $fields = CustomQueue::getSearchableFields($this->getRoot($root)); foreach ($this->getColumnPaths() as $path=>$descending) { @@ -2743,6 +2750,10 @@ extends VerySimpleModel { CustomQueue::getOrmPath($path, $query)); } } + // Add index hint if defined + if (($extra = $this->getExtra()) && isset($extra['index'])) { + $query->setOption(QuerySet::OPT_INDEX_HINT, $extra['index']); + } return $query; } @@ -2776,6 +2787,11 @@ extends VerySimpleModel { array('id' => $this->id)); } + function getAdvancedConfigForm($source=false) { + return new QueueSortAdvancedConfigForm($source ?: $this->getExtra(), + array('id' => $this->id)); + } + static function forQueue(CustomQueue $queue) { return static::objects()->filter([ 'root' => $queue->root ?: 'T', @@ -2811,6 +2827,11 @@ extends VerySimpleModel { $this->columns = JsonDataEncoder::encode($columns); } + if ($this->getExtra() !== null) { + $extra = $this->getAdvancedConfigForm($vars)->getClean(); + $this->extra = JsonDataEncoder::encode($extra); + } + if (count($errors)) return false; @@ -3070,3 +3091,24 @@ extends AbstractForm { ); } } + +class QueueSortAdvancedConfigForm +extends AbstractForm { + function getInstructions() { + return __('If unsure, leave these options blank and unset'); + } + + function buildFields() { + return array( + 'index' => new TextboxField(array( + 'label' => __('Database Index'), + 'hint' => __('Use this index when sorting on this column'), + 'required' => false, + 'layout' => new GridFluidCell(12), + 'configuration' => array( + 'placeholder' => __('Automatic'), + ), + )), + ); + } +} diff --git a/include/staff/templates/queue-sorting-edit.tmpl.php b/include/staff/templates/queue-sorting-edit.tmpl.php index 0a2d98b0246433b59ea0f9cc1d575deb3a4ed41b..a001201a2beb94e6c3391f2965e6353882dfc8c3 100644 --- a/include/staff/templates/queue-sorting-edit.tmpl.php +++ b/include/staff/templates/queue-sorting-edit.tmpl.php @@ -5,6 +5,7 @@ * $column - <QueueColumn> instance for this column */ $sortid = $sort->getId(); +$advanced = in_array('extra', $sort::getMeta()->getFieldNames()); ?> <h3 class="drag-handle"><?php echo __('Manage Sort Options'); ?> — <?php echo $sort->get('name') ?></h3> @@ -14,10 +15,30 @@ $sortid = $sort->getId(); <form method="post" action="#tickets/search/sort/edit/<?php echo $sortid; ?>"> +<?php if ($advanced) { ?> + <ul class="clean tabs"> + <li class="active"><a href="#fields"><i class="icon-columns"></i> + <?php echo __('Fields'); ?></a></li> + <li><a href="#advanced"><i class="icon-cog"></i> + <?php echo __('Advanced'); ?></a></li> + </ul> + + <div class="tab_content" id="fields"> +<?php } ?> + <?php include 'queue-sorting.tmpl.php'; ?> +<?php if ($advanced) { ?> + </div> + + <div class="hidden tab_content" id="advanced"> + <?php echo $sort->getAdvancedConfigForm()->asTable(); ?> + </div> + +<?php } ?> + <hr> <p class="full-width"> <span class="buttons pull-left"> diff --git a/scp/css/scp.css b/scp/css/scp.css index 878333317fb1d3e17f90f6d87dab46254a3b00f9..f255ae506c045beacf0499e528f31b4b5adee4b1 100644 --- a/scp/css/scp.css +++ b/scp/css/scp.css @@ -3525,6 +3525,12 @@ table.grid.form caption { margin-bottom: 5px; } +.grid.form .field > .field-hint-text { + font-style: italic; + margin: 0 10px 5px 10px; + opacity: 0.8; +} + #basic_search { background-color: #f4f4f4; margin: -10px 0;