diff --git a/administrator/components/com_content/models/article.php b/administrator/components/com_content/models/article.php index e062ed0d586c2..7160e1ccded85 100644 --- a/administrator/components/com_content/models/article.php +++ b/administrator/components/com_content/models/article.php @@ -241,7 +241,18 @@ protected function prepareTable($table) // Reorder the articles within the category so the new article is first if (empty($table->id)) { - $table->reorder('catid = ' . (int) $table->catid . ' AND state >= 0'); + $condition = 'catid = ' . (int) $table->catid . ' AND state >= 0'; + $table->ordering = $table->getEarlierOrder($condition); + + if ($table->ordering < 1) + { + // We have to reorder old ordering from 1,2,3, ... + // To ... ,2147483644, 2147483645, 2147483646 + $table->reorder($condition); + + // Get value again + $table->ordering = $table->getEarlierOrder($condition); + } } } @@ -504,7 +515,7 @@ public function save($data) $catid = CategoriesHelper::validateCategoryId($data['catid'], 'com_content'); } - // Save New Categoryg + // Save New Category if ($catid == 0 && $this->canCreateCategory()) { $table = array(); @@ -673,9 +684,22 @@ public function featured($pks, $value = 0) // Featuring. $tuples = array(); + $ordering = $table->getEarlierOrder(); + + if ($ordering < 1) + { + // We have to reorder old ordering from 1,2,3, ... + // To ... ,2147483644, 2147483645, 2147483646 + $table->reorder(); + + // Get value again + $ordering = $table->getEarlierOrder(); + } + foreach ($new_featured as $pk) { - $tuples[] = $pk . ', 0'; + $tuples[] = $pk . ', ' . $ordering; + $ordering--; } if (count($tuples)) @@ -698,8 +722,6 @@ public function featured($pks, $value = 0) return false; } - $table->reorder(); - $this->cleanCache(); return true; diff --git a/administrator/components/com_content/tables/featured.php b/administrator/components/com_content/tables/featured.php index 6b4e455649ce3..aec205fdea0d0 100644 --- a/administrator/components/com_content/tables/featured.php +++ b/administrator/components/com_content/tables/featured.php @@ -16,6 +16,14 @@ */ class ContentTableFeatured extends JTable { + /** + * Indicator that the column ordering use large numbers. + * + * @var boolean + * @since __DEPLOY_VERSION__ + */ + protected $_large_ordering_numbers = true; + /** * Constructor * diff --git a/libraries/joomla/table/table.php b/libraries/joomla/table/table.php index 26907ecdf4435..e5848437910a3 100644 --- a/libraries/joomla/table/table.php +++ b/libraries/joomla/table/table.php @@ -116,6 +116,14 @@ abstract class JTable extends JObject implements JObservableInterface, JTableInt */ protected $_jsonEncode = array(); + /** + * Indicator that the column ordering use large numbers. + * + * @var boolean + * @since __DEPLOY_VERSION__ + */ + protected $_large_ordering_numbers = false; + /** * Object constructor to set table and key fields. In most cases this will * be overridden by child classes to explicitly set the table and key fields @@ -1272,6 +1280,44 @@ public function isCheckedOut($with = 0, $against = null) return $checkedOut; } + /** + * Method to get the earlier ordering value for a group of rows defined by an SQL WHERE clause. + * + * This is useful for placing a new item first in a group of items in the table. + * + * @param string $where WHERE clause to use for selecting the MIN(ordering) for the table. + * + * @return integer The first free ordering value. + * + * @since __DEPLOY_VERSION__ + * @throws UnexpectedValueException + */ + public function getEarlierOrder($where = '') + { + // If there is no ordering field set an error and return false. + if (!property_exists($this, 'ordering')) + { + throw new UnexpectedValueException(sprintf('%s does not support ordering.', get_class($this))); + } + + // Get the least ordering value for a given where clause. + $query = $this->_db->getQuery(true) + ->select('COALESCE(MIN(ordering), 2147483647)') + ->from($this->_tbl) + ->where('ordering >= 0'); + + if ($where) + { + $query->where($where); + } + + $this->_db->setQuery($query); + $min = (int) $this->_db->loadResult(); + + // Return the first ordering value - 1. + return ($min - 1); + } + /** * Method to get the next ordering value for a group of rows defined by an SQL WHERE clause. * @@ -1354,12 +1400,15 @@ public function reorder($where = '') $k = $this->_tbl_key; + // To use more efficient alternative sort in descending order + $order_by = $this->_large_ordering_numbers ? 'ordering DESC' : 'ordering'; + // Get the primary keys and ordering values for the selection. $query = $this->_db->getQuery(true) ->select(implode(',', $this->_tbl_keys) . ', ordering') ->from($this->_tbl) ->where('ordering >= 0') - ->order('ordering'); + ->order($order_by); // Setup the extra where and ordering clause data. if ($where) @@ -1370,19 +1419,24 @@ public function reorder($where = '') $this->_db->setQuery($query); $rows = $this->_db->loadObjectList(); + // Last reserved number for alternative re-order + $last = 2147483647; + // Compact the ordering values. foreach ($rows as $i => $row) { // Make sure the ordering is a positive integer. if ($row->ordering >= 0) { + $ordering = $this->_large_ordering_numbers ? ($last - $i - 1) : ($i + 1); + // Only update rows that are necessary. - if ($row->ordering != $i + 1) + if ($row->ordering != $ordering) { // Update the row ordering field. $query->clear() ->update($this->_tbl) - ->set('ordering = ' . ($i + 1)); + ->set('ordering = ' . $ordering); $this->appendPrimaryKeys($query, $row); $this->_db->setQuery($query); $this->_db->execute(); diff --git a/libraries/legacy/table/content.php b/libraries/legacy/table/content.php index c7555b2d5b567..58ed484cd8905 100644 --- a/libraries/legacy/table/content.php +++ b/libraries/legacy/table/content.php @@ -19,6 +19,14 @@ */ class JTableContent extends JTable { + /** + * Indicator that the column ordering use large numbers. + * + * @var boolean + * @since __DEPLOY_VERSION__ + */ + protected $_large_ordering_numbers = true; + /** * Constructor *