From 85bae784f30d1777db15f43d2e3ce04a2c3e8653 Mon Sep 17 00:00:00 2001 From: Calin Burloiu Date: Wed, 7 Sep 2011 14:56:49 +0300 Subject: [PATCH] search implementation completed; video ordering feature when browsing by category added --- application/config/autoload.php | 2 +- application/config/config.php | 2 +- application/controllers/catalog.php | 68 +++++++++--- application/language/english/error_lang.php | 6 ++ application/language/english/ui_lang.php | 6 ++ application/models/videos_model.php | 100 +++++++++++++++--- .../views/catalog/search_results_view.php | 2 +- .../views/catalog/videos_summary_view.php | 32 +++++- application/views/error_view.php | 6 ++ application/views/header.php | 51 ++++++--- css/catalog.css | 12 +++ css/default.css | 1 + 12 files changed, 243 insertions(+), 45 deletions(-) create mode 100644 application/language/english/error_lang.php create mode 100644 application/views/error_view.php diff --git a/application/config/autoload.php b/application/config/autoload.php index bac0142..c3d8699 100644 --- a/application/config/autoload.php +++ b/application/config/autoload.php @@ -96,7 +96,7 @@ $autoload['config'] = array('p2p-tube'); | */ -$autoload['language'] = array('ui'); +$autoload['language'] = array('ui', 'error'); /* diff --git a/application/config/config.php b/application/config/config.php index 10b45e0..755fc91 100644 --- a/application/config/config.php +++ b/application/config/config.php @@ -126,7 +126,7 @@ $config['subclass_prefix'] = 'MY_'; | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! | */ -$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-'; +$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-+'; /* diff --git a/application/controllers/catalog.php b/application/controllers/catalog.php index 4966152..95a6908 100644 --- a/application/controllers/catalog.php +++ b/application/controllers/catalog.php @@ -86,7 +86,7 @@ class Catalog extends CI_Controller { $this->load->view('html_end'); } - public function category($category_name, $offset = 0) + public function category($category_name, $ordering = 'hottest', $offset = 0) { // ** // ** LOADING MODEL @@ -98,12 +98,14 @@ class Catalog extends CI_Controller { $this->load->model('videos_model'); $vs_data['videos'] = $this->videos_model->get_videos_summary( $vs_data['category_id'], intval($offset), - $this->config->item('videos_per_page')); + $this->config->item('videos_per_page'), $ordering); + + $vs_data['ordering'] = $ordering; // Pagination $this->load->library('pagination'); - $pg_config['base_url'] = site_url("catalog/category/$category_name/"); - $pg_config['uri_segment'] = 4; + $pg_config['base_url'] = site_url("catalog/category/$category_name/$ordering/"); + $pg_config['uri_segment'] = 5; $pg_config['total_rows'] = $this->videos_model->get_videos_count( $vs_data['category_id']); $pg_config['per_page'] = $this->config->item('videos_per_page'); @@ -127,7 +129,10 @@ class Catalog extends CI_Controller { // ** LOADING VIEWS // ** $this->load->view('html_begin', $this->html_head_params); - $this->load->view('header'); + $this->load->view('header', array( + 'search_category_name'=>$vs_data['category_name'], + 'search_category_title'=>$vs_data['category_title'] + )); // $main_params['content'] = $this->load->view('catalog/category_view', $data, TRUE); $main_params['content'] = @@ -146,28 +151,43 @@ class Catalog extends CI_Controller { $str_post_search = $this->input->post('search', TRUE); if ($search_query === "" && $str_post_search !== FALSE) redirect('catalog/search/'. $this->input->post('search', TRUE)); + + $this->load->model('videos_model'); // ** // ** LOADING MODEL // ** + // Search query is encoded for URL and must be decoded. + $enc_search_query = $search_query; + $search_query = $this->videos_model->decode_search_query($search_query); + $results_data['search_query'] = $search_query; + // Category $results_data = $this->_get_category_data($category_name); if ($results_data === NULL) $results_data = array('category_id'=>NULL); - $results_data['search_query'] = $search_query; + // Page header data + $header_data['search_query'] = $search_query; + if ($category_name !== NULL) + { + $header_data['search_category_name'] = $results_data['category_name']; + $header_data['search_category_title'] = $results_data['category_title']; + } // Check if search string is valid. if (strlen($search_query) < 4) { - $results_data['videos'] = NULL; + //$results_data['videos'] = NULL; + $this->error($this->lang->line('error_search_query_too_short'), + $header_data); + return; } else { // Retrieve search results. - $this->load->model('videos_model'); $results_data['count'] = $this->videos_model->search_videos( - $search_query); + $search_query, 0, 0, $results_data['category_id']); $results_data['videos'] = $this->videos_model->search_videos( $search_query, intval($offset), $this->config->item('search_results_per_page'), @@ -177,7 +197,7 @@ class Catalog extends CI_Controller { // Pagination $this->load->library('pagination'); - $pg_config['base_url'] = site_url("catalog/search/$search_query/"); + $pg_config['base_url'] = site_url("catalog/search/$enc_search_query/"); $pg_config['uri_segment'] = 4; $pg_config['total_rows'] = $results_data['count']; $pg_config['per_page'] = @@ -185,7 +205,8 @@ class Catalog extends CI_Controller { $this->pagination->initialize($pg_config); $results_data['pagination'] = $this->pagination->create_links(); } - + + // HTML head parameters $params = array( 'title' => $this->config->item('site_name'), 'css' => array( 'catalog.css' @@ -199,7 +220,7 @@ class Catalog extends CI_Controller { // ** LOADING VIEWS // ** $this->load->view('html_begin', $this->html_head_params); - $this->load->view('header'); + $this->load->view('header', $header_data); // Search Results $main_params['content'] = @@ -212,6 +233,29 @@ class Catalog extends CI_Controller { $this->load->view('html_end'); } + public function error($msg, $header_data) + { + $params = array( 'title' => 'Error - '. $this->config->item('site_name'), + //'css' => array(), + //'js' => array(), + //'metas' => array('description'=>'','keywords'=>'') + ); + $this->load->library('html_head_params', $params); + + // ** + // ** LOADING VIEWS + // ** + $this->load->view('html_begin', $this->html_head_params); + $this->load->view('header', $header_data); + + $main_params['content'] = $this->load->view('error_view', array('msg'=>$msg), TRUE); + $main_params['side'] = $this->load->view('side_default', NULL, TRUE); + $this->load->view('main', $main_params); + + $this->load->view('footer'); + $this->load->view('html_end'); + } + public function _get_category_data($category_name) { if ($category_name === NULL) diff --git a/application/language/english/error_lang.php b/application/language/english/error_lang.php new file mode 100644 index 0000000..ae3448f --- /dev/null +++ b/application/language/english/error_lang.php @@ -0,0 +1,6 @@ + + *
  • 'hottest': newest most appreciated first. An + * appreciated video is one which has a bigger + * score = views + likes - dislikes.
  • + *
  • 'newest': newest first.
  • + *
  • 'alphabetically': sort alphabetically.
  • + * * @return array a list of videos, each one being an assoc array with: * */ - public function get_videos_summary($category_id, $offset, $count) + public function get_videos_summary($category_id, $offset, $count, $ordering = 'hottest') { $this->load->helper('text'); + // Ordering + switch ($ordering) + { + case 'hottest': + $order_statement = "ORDER BY date DESC, score DESC, RAND()"; + break; + case 'newest': + $order_statement = "ORDER BY date DESC"; + break; + case 'alphabetically': + $order_statement = "ORDER BY title"; + break; + + default: + $order_statement = ""; + } + $query = $this->db->query( - 'SELECT id, name, title, duration, user_id, views, thumbs_count, - default_thumb + "SELECT id, name, title, duration, user_id, views, thumbs_count, + default_thumb, (views + likes - dislikes) AS score FROM `videos` WHERE category_id = ? - ORDER BY name - LIMIT ?, ?', // TODO summary order + $order_statement + LIMIT ?, ?", array(intval($category_id), $offset, $count)); if ($query->num_rows() > 0) @@ -213,15 +238,36 @@ class Videos_model extends CI_Model { */ public function search_videos($search_query, $offset = 0, $count = 0, $category_id = NULL) - { + { + if (! $this->is_advanced_search_query($search_query)) // if natural language mode + { + $search_cond = "MATCH (title, description, tags) + AGAINST ('$search_query')"; + $relevance = "$search_cond AS relevance"; + } // if boolean mode + else + { + $against = "AGAINST ('$search_query' IN BOOLEAN MODE)"; + $search_cond = "MATCH (title, description, tags) + $against"; + $relevance = "( (0.5 * (MATCH(title) $against)) + + (0.3 * (MATCH(tags) $against)) + + (0.2 * (MATCH(description) $against)) ) AS relevance"; + } + if ($count === 0) { $selected_columns = "COUNT(*) count"; + $order = ""; $limit = ""; } else { - $selected_columns = "id, name, title, duration, user_id, views, thumbs_count, default_thumb, date, description"; + $selected_columns = "id, name, title, duration, user_id, views, + thumbs_count, default_thumb, date, description, + (views + likes - dislikes) AS score, + $relevance"; + $order = "ORDER BY relevance DESC, score DESC"; $limit = "LIMIT $offset, $count"; } @@ -232,12 +278,12 @@ class Videos_model extends CI_Model { $search_query = trim($search_query); - $query = $this->db->query( - "SELECT $selected_columns + $str_query = "SELECT $selected_columns FROM `videos` - WHERE $category_cond MATCH (title, description, tags) AGAINST (?) - $limit", - array($search_query)); + WHERE $category_cond $search_cond + $order + $limit"; + $query = $this->db->query($str_query); if ($query->num_rows() > 0) { @@ -271,6 +317,34 @@ class Videos_model extends CI_Model { return $videos; } + + public function decode_search_query($search_query) + { + $search_query = urldecode($search_query); + + $search_query = str_replace('_AST_', '*', $search_query); + $search_query = str_replace('_AND_', '+', $search_query); + $search_query = str_replace('_GT_', '>', $search_query); + $search_query = str_replace('_LT_', '<', $search_query); + $search_query = str_replace('_PO_', '(', $search_query); + $search_query = str_replace('_PC_', ')', $search_query); + $search_query = str_replace('_LOW_', '~', $search_query); + $search_query = str_replace('_QUO_', '"', $search_query); + + return $search_query; + } + + /** + * Return TRUE if it contains any special caracter from an advanced search + * query. + * @param string $search_query + * @return boolean + */ + public function is_advanced_search_query($search_query) + { + return (preg_match('/\*|\+|\-|>|\<|\(|\)|~|"/', $search_query) == 0 + ? FALSE : TRUE); + } } /* End of file videos_model.php */ diff --git a/application/views/catalog/search_results_view.php b/application/views/catalog/search_results_view.php index 38f036d..f6146d4 100644 --- a/application/views/catalog/search_results_view.php +++ b/application/views/catalog/search_results_view.php @@ -1,6 +1,6 @@

    lang->line('ui_search_results_for') - . " «$search_query»" ?>

    + . " «" . htmlentities($search_query) . "»" ?>

    lang->line('ui_results'); ?>

    diff --git a/application/views/catalog/videos_summary_view.php b/application/views/catalog/videos_summary_view.php index 25e496b..66e5f29 100644 --- a/application/views/catalog/videos_summary_view.php +++ b/application/views/catalog/videos_summary_view.php @@ -4,6 +4,21 @@ + + $this->lang->line('ui_show_hottest'), + 'newest'=> $this->lang->line('ui_show_newest'), + 'alphabetically'=> $this->lang->line('ui_sort_alphabetically') + ); + + echo '

    '; + echo form_dropdown('ordering', $ordering_opts, $ordering, 'id="ordering"'); + echo '

    '; + } + ?> @@ -38,4 +53,19 @@
    -
    \ No newline at end of file + + + \ No newline at end of file diff --git a/application/views/error_view.php b/application/views/error_view.php new file mode 100644 index 0000000..e83c7d3 --- /dev/null +++ b/application/views/error_view.php @@ -0,0 +1,6 @@ +
    +

    + + +

    +
    \ No newline at end of file diff --git a/application/views/header.php b/application/views/header.php index 14047e1..987b6c4 100644 --- a/application/views/header.php +++ b/application/views/header.php @@ -1,6 +1,11 @@ - +