-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
[4.0] com_finder: add search statistics #20681
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
edf1cd3
24b6b01
8e0c79b
ff57a95
79441d5
add104e
736d005
a25c0e5
82ae14a
c8558c4
8ed03d7
5f7e4ff
9e1f71a
780205e
3c7781a
9f617e9
7eeab91
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| CREATE TABLE IF NOT EXISTS `#__finder_logging` ( | ||
| `searchterm` VARCHAR(255) NOT NULL DEFAULT '', | ||
| `md5sum` VARCHAR(32) NOT NULL DEFAULT '', | ||
| `query` BLOB NOT NULL, | ||
| `hits` INT(11) NOT NULL DEFAULT '1', | ||
| `results` INT(11) NOT NULL DEFAULT '0', | ||
| UNIQUE INDEX `md5sum` (`md5sum`), | ||
| INDEX `searchterm` (`searchterm`) | ||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| CREATE TABLE IF NOT EXISTS "#__finder_logging" ( | ||
| "searchterm" character varying(255) NOT NULL DEFAULT '', | ||
| "md5sum" character varying(32) NOT NULL DEFAULT '', | ||
| "query" bytes NOT NULL, | ||
| "hits" integer NOT NULL DEFAULT 1, | ||
| "results" integer NOT NULL DEFAULT 0, | ||
| CONSTRAINT "#__finder_logging_idx_md5sum" UNIQUE ("md5sum") | ||
| ); | ||
| CREATE INDEX "#__finder_logging_idx_md5sum" on "#__finder_logging" ("md5sum"); | ||
| CREATE INDEX "#__finder_logging_idx_searchterm" on "#__finder_logging" ("searchterm"); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| <?php | ||
| /** | ||
| * @package Joomla.Administrator | ||
| * @subpackage com_finder | ||
| * | ||
| * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved. | ||
| * @license GNU General Public License version 2 or later; see LICENSE.txt | ||
| */ | ||
| namespace Joomla\Component\Finder\Administrator\Controller; | ||
|
|
||
| defined('_JEXEC') or die; | ||
|
|
||
| use Joomla\CMS\MVC\Controller\BaseController; | ||
|
|
||
| /** | ||
| * Methods supporting a list of search terms. | ||
| * | ||
| * @since __DEPLOY_VERSION__ | ||
| */ | ||
| class SearchesController extends BaseController | ||
| { | ||
| /** | ||
| * Method to reset the search log table. | ||
| * | ||
| * @return boolean | ||
| */ | ||
| public function reset() | ||
| { | ||
| // Check for request forgeries. | ||
| \JSession::checkToken() or jexit(\JText::_('JINVALID_TOKEN')); | ||
|
|
||
| $model = $this->getModel('Searches'); | ||
|
|
||
| if (!$model->reset()) | ||
| { | ||
| $this->app->enqueueMessage($model->getError(), 'error'); | ||
| } | ||
|
|
||
| $this->setRedirect('index.php?option=com_finder&view=searches'); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| <?php | ||
| /** | ||
| * @package Joomla.Administrator | ||
| * @subpackage com_finder | ||
| * | ||
| * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved. | ||
| * @license GNU General Public License version 2 or later; see LICENSE.txt | ||
| */ | ||
| namespace Joomla\Component\Finder\Administrator\Model; | ||
|
|
||
| defined('_JEXEC') or die; | ||
|
|
||
| use Joomla\CMS\Component\ComponentHelper; | ||
| use Joomla\CMS\MVC\Model\ListModel; | ||
| use Joomla\CMS\MVC\Factory\MVCFactoryInterface; | ||
| use Joomla\CMS\Plugin\PluginHelper; | ||
|
|
||
| /** | ||
| * Methods supporting a list of search terms. | ||
| * | ||
| * @since __DEPLOY_VERSION__ | ||
| */ | ||
| class SearchesModel extends ListModel | ||
| { | ||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param array $config An optional associative array of configuration settings. | ||
| * @param MVCFactoryInterface $factory The factory. | ||
| * | ||
| * @see \Joomla\CMS\MVC\Model\BaseDatabaseModel | ||
| * @since __DEPLOY_VERSION__ | ||
| */ | ||
| public function __construct($config = array(), MVCFactoryInterface $factory = null) | ||
| { | ||
| if (empty($config['filter_fields'])) | ||
| { | ||
| $config['filter_fields'] = array( | ||
| 'search_term', 'a.search_term', | ||
| 'hits', 'a.hits', | ||
| ); | ||
| } | ||
|
|
||
| parent::__construct($config, $factory); | ||
| } | ||
|
|
||
| /** | ||
| * Method to auto-populate the model state. | ||
| * | ||
| * Note. Calling getState in this method will result in recursion. | ||
| * | ||
| * @param string $ordering An optional ordering field. | ||
| * @param string $direction An optional direction (asc|desc). | ||
| * | ||
| * @return void | ||
| * | ||
| * @since __DEPLOY_VERSION__ | ||
| */ | ||
| protected function populateState($ordering = 'a.hits', $direction = 'asc') | ||
| { | ||
| // Special state for toggle results button. | ||
| $this->setState('show_results', $this->getUserStateFromRequest($this->context . '.show_results', 'show_results', 1, 'int')); | ||
|
|
||
| // Load the parameters. | ||
| $params = ComponentHelper::getParams('com_finder'); | ||
| $this->setState('params', $params); | ||
|
|
||
| // List state information. | ||
| parent::populateState($ordering, $direction); | ||
| } | ||
|
|
||
| /** | ||
| * Method to get a store id based on model configuration state. | ||
| * | ||
| * This is necessary because the model is used by the component and | ||
| * different modules that might need different sets of data or different | ||
| * ordering requirements. | ||
| * | ||
| * @param string $id A prefix for the store id. | ||
| * | ||
| * @return string A store id. | ||
| * | ||
| * @since __DEPLOY_VERSION__ | ||
| */ | ||
| protected function getStoreId($id = '') | ||
| { | ||
| // Compile the store id. | ||
| $id .= ':' . $this->getState('show_results'); | ||
| $id .= ':' . $this->getState('filter.search'); | ||
|
|
||
| return parent::getStoreId($id); | ||
| } | ||
|
|
||
| /** | ||
| * Build an SQL query to load the list data. | ||
| * | ||
| * @return \JDatabaseQuery | ||
| * | ||
| * @since __DEPLOY_VERSION__ | ||
| */ | ||
| protected function getListQuery() | ||
| { | ||
| // Create a new query object. | ||
| $db = $this->getDbo(); | ||
| $query = $db->getQuery(true); | ||
|
|
||
| // Select the required fields from the table. | ||
| $query->select( | ||
| $this->getState( | ||
| 'list.select', | ||
| 'a.*' | ||
| ) | ||
| ); | ||
| $query->from($db->quoteName('#__finder_logging', 'a')); | ||
|
|
||
| // Filter by search in title | ||
| if ($search = $this->getState('filter.search')) | ||
| { | ||
| $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%')); | ||
| $query->where($db->quoteName('a.searchterm') . ' LIKE ' . $search); | ||
| } | ||
|
|
||
| // Add the list ordering clause. | ||
| $query->order($db->escape($this->getState('list.ordering', 'a.hits')) . ' ' . $db->escape($this->getState('list.direction', 'ASC'))); | ||
|
|
||
| return $query; | ||
| } | ||
|
|
||
| /** | ||
| * Override the parent getItems to inject optional data. | ||
| * | ||
| * @return mixed An array of objects on success, false on failure. | ||
| * | ||
| * @since __DEPLOY_VERSION__ | ||
| */ | ||
| public function getItems() | ||
| { | ||
| $items = parent::getItems(); | ||
|
|
||
| \JLoader::register('FinderIndexerQuery', JPATH_COMPONENT_ADMINISTRATOR . '/helpers/indexer/query.php'); | ||
| \JLoader::register('FinderIndexerToken', JPATH_COMPONENT_ADMINISTRATOR . '/helpers/indexer/token.php'); | ||
|
|
||
| foreach ($items as $item) | ||
| { | ||
| $item->query = unserialize($item->query); | ||
| } | ||
|
|
||
| return $items; | ||
| } | ||
|
|
||
| /** | ||
| * Method to reset the search log table. | ||
| * | ||
| * @return boolean | ||
| * | ||
| * @since __DEPLOY_VERSION__ | ||
| */ | ||
| public function reset() | ||
| { | ||
| $db = $this->getDbo(); | ||
|
|
||
| try | ||
| { | ||
| $db->truncateTable('#__finder_logging'); | ||
| } | ||
| catch (\RuntimeException $e) | ||
| { | ||
| $this->setError($e->getMessage()); | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| <?php | ||
| /** | ||
| * @package Joomla.Administrator | ||
| * @subpackage com_finder | ||
| * | ||
| * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved. | ||
| * @license GNU General Public License version 2 or later; see LICENSE.txt | ||
| */ | ||
| namespace Joomla\Component\Finder\Administrator\View\Searches; | ||
|
|
||
| defined('_JEXEC') or die; | ||
|
|
||
| use Joomla\CMS\Helper\ContentHelper; | ||
| use Joomla\CMS\Toolbar\Toolbar; | ||
| use Joomla\CMS\Toolbar\ToolbarHelper; | ||
| use Joomla\Component\Finder\Administrator\Helper\FinderHelper; | ||
| use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; | ||
|
|
||
| /** | ||
| * View class for a list of search terms. | ||
| * | ||
| * @since 4.0 | ||
| */ | ||
| class HtmlView extends BaseHtmlView | ||
| { | ||
| /** | ||
| * True if gathering search statistics is enabled | ||
| * | ||
| * @var boolean | ||
| */ | ||
| protected $enabled; | ||
|
|
||
| /** | ||
| * An array of items | ||
| * | ||
| * @var array | ||
| */ | ||
| protected $items; | ||
|
|
||
| /** | ||
| * The pagination object | ||
| * | ||
| * @var \Joomla\CMS\Pagination\Pagination | ||
| */ | ||
| protected $pagination; | ||
|
|
||
| /** | ||
| * The model state | ||
| * | ||
| * @var \JObject | ||
| */ | ||
| protected $state; | ||
|
|
||
| /** | ||
| * Form object for search filters | ||
| * | ||
| * @var \JForm | ||
| * @since 4.0.0 | ||
| */ | ||
| public $filterForm; | ||
|
|
||
| /** | ||
| * The active search filters | ||
| * | ||
| * @var array | ||
| * @since 4.0.0 | ||
| */ | ||
| public $activeFilters; | ||
|
|
||
| /** | ||
| * The actions the user is authorised to perform | ||
| * | ||
| * @var \JObject | ||
| * @since 4.0.0 | ||
| */ | ||
| protected $canDo; | ||
|
|
||
| /** | ||
| * Display the view. | ||
| * | ||
| * @param string $tpl The name of the template file to parse; automatically searches through the template paths. | ||
| * | ||
| * @return mixed A string if successful, otherwise an Error object. | ||
| */ | ||
| public function display($tpl = null) | ||
| { | ||
| $app = \JFactory::getApplication(); | ||
| $this->items = $this->get('Items'); | ||
| $this->pagination = $this->get('Pagination'); | ||
| $this->state = $this->get('State'); | ||
| $this->filterForm = $this->get('FilterForm'); | ||
| $this->activeFilters = $this->get('ActiveFilters'); | ||
| $this->enabled = $this->state->params->get('logging_enabled'); | ||
| $this->canDo = ContentHelper::getActions('com_finder'); | ||
|
|
||
| // Check for errors. | ||
| if (count($errors = $this->get('Errors'))) | ||
| { | ||
| throw new \JViewGenericdataexception(implode("\n", $errors), 500); | ||
| } | ||
|
|
||
| FinderHelper::addSubmenu('searches'); | ||
|
|
||
| // Check if plugin is enabled | ||
| if ($this->enabled) | ||
| { | ||
| $app->enqueueMessage(\JText::_('COM_FINDER_LOGGING_ENABLED'), 'notice'); | ||
| } | ||
| else | ||
| { | ||
| $app->enqueueMessage(\JText::_('COM_FINDER_LOGGING_DISABLED'), 'warning'); | ||
| } | ||
|
|
||
| // Prepare the view. | ||
| $this->addToolbar(); | ||
| $this->sidebar = \JHtmlSidebar::render(); | ||
|
|
||
| return parent::display($tpl); | ||
| } | ||
|
|
||
| /** | ||
| * Add the page title and toolbar. | ||
| * | ||
| * @return void | ||
| * | ||
| * @since 1.6 | ||
| */ | ||
| protected function addToolbar() | ||
| { | ||
| $canDo = $this->canDo; | ||
|
|
||
| ToolbarHelper::title(\JText::_('COM_FINDER_MANAGER_SEARCHES'), 'search'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see you use JText for all strings. Why not use the new Text class?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It honestly doesn't matter either way right now if namespaced or aliased global classes are used.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I know, that is why I ask. Thank for answer |
||
|
|
||
| if ($canDo->get('core.edit.state')) | ||
| { | ||
| ToolbarHelper::custom('searches.reset', 'refresh.png', 'refresh_f2.png', 'JSEARCH_RESET', false); | ||
| } | ||
|
|
||
| ToolbarHelper::divider(); | ||
|
|
||
| if ($canDo->get('core.admin') || $canDo->get('core.options')) | ||
| { | ||
| ToolbarHelper::preferences('com_finder'); | ||
| } | ||
|
|
||
| ToolbarHelper::help('JHELP_COMPONENTS_FINDER_MANAGE_SEARCHES'); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Index has to be limited to the first 191 characters. See issue #21235