Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 69 additions & 18 deletions libraries/src/Form/Field/TagField.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,11 @@ protected function getOptions()
$published = $this->element['published'] ?: array(0, 1);
$app = Factory::getApplication();
$language = null;
$options = [];

// Return only basic options, everything else will be searched via AJAX
if ($this->isRemoteSearch() && !$this->value)
{
return parent::getOptions();
}
// This limit is only used with isRemoteSearch
$prefillLimit = 30;
$isRemoteSearch = $this->isRemoteSearch();

$db = Factory::getDbo();
$query = $db->getQuery(true)
Expand Down Expand Up @@ -184,12 +183,6 @@ protected function getOptions()

$query->where($db->quoteName('a.lft') . ' > 0');

// Preload only active values, everything else will be searched via AJAX
if ($this->isRemoteSearch() && $this->value)
{
$query->whereIn($db->quoteName('a.id'), $this->value);
}

// Filter on the published state
if (is_numeric($published))
{
Expand All @@ -205,16 +198,74 @@ protected function getOptions()

$query->order($db->quoteName('a.lft') . ' ASC');

// Get the options.
$db->setQuery($query);

try
// Preload only active values and 30 most used tags or fill up
if ($isRemoteSearch)
{
$options = $db->loadObjectList();
// Load the most $prefillLimit used tags
$topQuery = $db->getQuery(true)
->select($db->quoteName('tag_id'))
->from($db->quoteName('#__contentitem_tag_map'))
->group($db->quoteName('tag_id'))
->order('count(*)')
->setLimit($prefillLimit);

$db->setQuery($topQuery);
$topIds = $db->loadColumn();

// Merge the used values into the most used tags
if (!empty($this->value) && is_array($this->value))
{
$topIds = array_merge($topIds, $this->value);
$topIds = array_keys(array_flip($topIds));
}

// Set the default limit for the main query
$query->setLimit($prefillLimit);

if (!empty($topIds))
{
// Filter the ids to the most used tags and the selected tags
$preQuery = clone $query;
$preQuery->whereIn($db->quoteName('a.id'), $topIds);

$db->setQuery($preQuery);

try
{
$options = $db->loadObjectList();
}
catch (\RuntimeException $e)
{
return array();
}

// Limit the main query to the missing amount of tags
$count = count($options);
$prefillLimit = $prefillLimit - $count;
$query->setLimit($prefillLimit);

// Exclude the already loaded tags from the main query
if ($count > 0)
{
$query->whereNotIn($db->quoteName('a.id'), ArrayHelper::getColumn($options, 'value'));
}
}
}
catch (\RuntimeException $e)

// Only execute the query if we need more tags not already loaded by the $preQuery query
if (!$isRemoteSearch || $prefillLimit > 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this code always going to run because $prefillLimit is set to 30 (and even in the previous version of your code if this was a parameter unless that param had been set to 0)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$prefiilLimit is set in line 244

{
return array();
// Get the options.
$db->setQuery($query);

try
{
$options = array_merge($options, $db->loadObjectList());
}
catch (\RuntimeException $e)
{
return array();
}
}

// Block the possibility to set a tag as it own parent
Expand Down