diff --git a/src/com_xbbooks/admin/models/reviews.php b/src/com_xbbooks/admin/models/reviews.php index dc36b4d..969bc3b 100644 --- a/src/com_xbbooks/admin/models/reviews.php +++ b/src/com_xbbooks/admin/models/reviews.php @@ -2,7 +2,7 @@ /******* * @package xbBooks * @filesource admin/models/reviews.php - * @version 1.0.1.3 5th January 2023 + * @version 1.0.3.7 24th January 2023 * @author Roger C-O * @copyright Copyright (c) Roger Creagh-Osborne, 2021 * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html @@ -60,6 +60,9 @@ protected function getListQuery() { } elseif (stripos($search,'s:')===0) { $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim(substr($search,2)), true) . '%')); $query->where('a.review' . ' LIKE ' . $search.' OR a.summary LIKE '.$search); + } elseif (stripos($search,'b:')===0) { + $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim(substr($search,2)), true) . '%')); + $query->where('b.title' . ' LIKE ' . $search); } elseif (stripos($search,':')!= 1) { $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%')); $query->where('(a.title LIKE ' . $search .') OR (a.alias LIKE ' . $search .')'); diff --git a/src/com_xbbooks/site/controllers/bookreviews.php b/src/com_xbbooks/site/controllers/bookreviews.php new file mode 100644 index 0000000..3ee9b89 --- /dev/null +++ b/src/com_xbbooks/site/controllers/bookreviews.php @@ -0,0 +1,16 @@ +getParams(); + $this->setState('params', $params); + + $categoryId = $app->getUserStateFromRequest('catid', 'catid',''); + $app->setUserState('catid', ''); + $this->setState('categoryId',$categoryId); + $tagId = $app->getUserStateFromRequest('tagid', 'tagid',''); + $app->setUserState('tagid', ''); + $this->setState('tagId',$tagId); + + parent::populateState($ordering, $direction); + + //pagination limit + $limit = $this->getUserStateFromRequest($this->context.'.limit', 'limit', 25 ); + $this->setState('limit', $limit); + $this->setState('list.limit', $limit); + $limitstart = $app->getUserStateFromRequest('limitstart', 'limitstart', $app->get('start')); + $this->setState('list.start', $limitstart); + + } + + protected function getListQuery() { + // Initialize variables. + $db = Factory::getDbo(); + $query = $db->getQuery(true); + + // Create the base select statement. + $query->select('a.id AS id, a.title AS title, a.alias AS alias, a.summary AS summary, a.catid AS catid, + a.review AS review, a.rating AS rating, a.state AS published, a.reviewer AS reviewer, + a.created_by AS created_by, a.rev_date AS rev_date, a.note as note, a.ordering AS ordering, + a.params AS params, + a.checked_out AS checked_out, a.checked_out_time AS checked_out_time, a.created AS created') + ->from($db->quoteName('#__xbbookreviews','a')); + + $query->select('c.title AS category_title') + ->join('LEFT', '#__categories AS c ON c.id = a.catid'); + + // Join with books table to get the book title + $query->select($db->quoteName('b.id','bookid').','.$db->quoteName('b.title', 'booktitle')) + ->join('LEFT', $db->quoteName('#__xbbooks', 'b') . ' ON b.id = a.book_id'); + + // Filter by search in title/id/summary/biog + $search = $this->getState('filter.search'); + + if (!empty($search)) { + if (stripos($search, 'i:') === 0) { + $query->where($db->quoteName('a.id') . ' = ' . (int) substr($search, 2)); + } elseif (stripos($search,'s:')===0) { + $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim(substr($search,2)), true) . '%')); + $query->where('a.review' . ' LIKE ' . $search.' OR a.summary LIKE '.$search); + } elseif (stripos($search,'b:')===0) { + $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim(substr($search,2)), true) . '%')); + $query->where('b.title' . ' LIKE ' . $search); + } elseif (stripos($search,':')!= 1) { + $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%')); + $query->where('(a.title LIKE ' . $search .') OR (a.alias LIKE ' . $search .')'); + } + } + + // Filter by published state + $query->where('a.state = 1 '); + + $searchbar = (int)$this->getState('params')['search_bar']; + //if a menu filter is set this takes priority and serch filter field is hidden + + // Filter by category + $categoryId = $this->getState('categoryId'); + $this->setState('categoryId',''); + if (empty($categoryId)) { + $categoryId = $this->getState('params')['menu_category_id']; + } + if (($searchbar==1) && ($categoryId==0)){ + $categoryId = $this->getState('filter.category_id'); + } + if ((is_numeric($categoryId)) && ($categoryId > 0) ){ + $query->where($db->quoteName('a.catid') . ' = ' . (int) $categoryId); + } elseif (is_array($categoryId)) { + $catlist = implode(',', $categoryId); + $query->where($db->quoteName('a.catid') . ' IN ('.$catlist.')'); + } + + //Filter by rating + $ratfilt = $this->getState('filter.ratfilt'); + if (is_numeric($ratfilt)) { + $query->where('a.rating = '.$ratfilt); + } + + //filter by tags + $tagfilt = $this->getState('tagId'); + // $this->setState('tagId',''); + $taglogic = 0; + if (empty($tagfilt)) { //look for menu options + $tagfilt = $this->getState('params')['menu_tag']; + $taglogic = $this->getState('params')['menu_taglogic']; //1=AND otherwise OR + } + if ((!is_array($tagfilt)) && (!empty($tagfilt))) { + $tagfilt = array($tagfilt); + } + + if (($searchbar==1) && (empty($tagfilt))) { + //look for filter options and ignore menu options + $tagfilt = $this->getState('filter.tagfilt'); + $taglogic = $this->getState('filter.taglogic'); //1=AND otherwise OR + } + + if (empty($tagfilt)) { + $subQuery = '(SELECT content_item_id FROM #__contentitem_tag_map + WHERE type_alias LIKE '.$db->quote('com_xbbooks.review').')'; + if ($taglogic === '1') { + $query->where('a.id NOT IN '.$subQuery); + } elseif ($taglogic === '2') { + $query->where('a.id IN '.$subQuery); + } + } else { + $tagfilt = ArrayHelper::toInteger($tagfilt); + $subquery = '(SELECT tmap.tag_id AS tlist FROM #__contentitem_tag_map AS tmap + WHERE tmap.type_alias = '.$db->quote('com_xbbooks.review').' + AND tmap.content_item_id = a.id)'; + switch ($taglogic) { + case 1: //all + for ($i = 0; $i < count($tagfilt); $i++) { + $query->where($tagfilt[$i].' IN '.$subquery); + } + break; + case 2: //none + for ($i = 0; $i < count($tagfilt); $i++) { + $query->where($tagfilt[$i].' NOT IN '.$subquery); + } + break; + default: //any + if (count($tagfilt)==1) { + $query->where($tagfilt[0].' IN '.$subquery); + } else { + $tagIds = implode(',', $tagfilt); + if ($tagIds) { + $subQueryAny = '(SELECT DISTINCT content_item_id FROM #__contentitem_tag_map + WHERE tag_id IN ('.$tagIds.') AND type_alias = '.$db->quote('com_xbbooks.review').')'; + $query->innerJoin('(' . (string) $subQueryAny . ') AS tagmap ON tagmap.content_item_id = a.id'); + } + } + break; + } + } //end if $tagfilt + + // Add the list ordering clause. + $orderCol = $this->state->get('list.ordering', 'rev_date'); + $orderDirn = $this->state->get('list.direction', 'DESC'); + switch($orderCol) { + case 'a.ordering' : + case 'a.catid' : + //needs a menu option to set orderCol to ordering. Also menu option to alllow user to reorder on table + $query->order('category_title '.$orderDirn.', a.ordering'); + break; + case 'category_title': + $query->order('category_title '.$orderDirn.', title'); + break; + default: + $query->order($db->escape($orderCol.' '.$orderDirn)); + break; + } + + $query->group('a.id'); + + return $query; + } + + public function getItems() { + $items = parent::getItems(); + $tagsHelper = new TagsHelper; + foreach ($items as $i=>$item) { + $item->tags = $tagsHelper->getItemTags('com_xbbooks.review' , $item->id); + } + return $items; + } +} diff --git a/src/com_xbbooks/site/models/forms/filter_bookreviews.xml b/src/com_xbbooks/site/models/forms/filter_bookreviews.xml new file mode 100644 index 0000000..5ce2bee --- /dev/null +++ b/src/com_xbbooks/site/models/forms/filter_bookreviews.xml @@ -0,0 +1,66 @@ + + +
+ + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/src/com_xbbooks/site/router.php b/src/com_xbbooks/site/router.php index 7b38817..218aabb 100644 --- a/src/com_xbbooks/site/router.php +++ b/src/com_xbbooks/site/router.php @@ -85,7 +85,7 @@ public function parse(&$segments) $vars['view'] = 'categories'; break; case 'bookreviews': - $vars['view'] = 'blog'; + $vars['view'] = 'bookreviews'; break; case 'tags': $vars['view'] = 'tags'; diff --git a/src/com_xbbooks/site/views/bookreviews/index.html b/src/com_xbbooks/site/views/bookreviews/index.html new file mode 100644 index 0000000..3af6301 --- /dev/null +++ b/src/com_xbbooks/site/views/bookreviews/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/com_xbbooks/site/views/bookreviews/tmpl/default.php b/src/com_xbbooks/site/views/bookreviews/tmpl/default.php new file mode 100644 index 0000000..f5984bb --- /dev/null +++ b/src/com_xbbooks/site/views/bookreviews/tmpl/default.php @@ -0,0 +1,237 @@ + Text::_('XBCULTURE_SELECT_TAGS'))); +HTMLHelper::_('formbehavior.chosen', '.multipleCats', null, array('placeholder_text_multiple' => Text::_('XBCULTURE_SELECT_CATS'))); +HTMLHelper::_('formbehavior.chosen', 'select'); + +$user = Factory::getUser(); +$userId = $user->get('id'); +$listOrder = $this->escape($this->state->get('list.ordering')); +$listDirn = $this->escape(strtolower($this->state->get('list.direction'))); +if (!$listOrder) { + $listOrder='rev_date'; + $listDirn = 'descending'; +} +$orderNames = array('title'=>Text::_('XBCULTURE_TITLE'),'booktitle'=>Text::_('XBBOOKS_BOOKTITLE'), + 'id'=>'id','rev_date'=>Text::_('XBCULTURE_REVIEW_DATE'),'category_title'=>Text::_('XBCULTURE_CATEGORY'), + 'published'=>Text::_('XBCULTURE_STATUS'),'ordering'=>Text::_('XBCULTURE_ORDERING'), + 'rating'=>Text::_('XBCULTURE_RATING'),'a.created'=>Text::_('XBCULTURE_DATE_ADDED') +); + +$bvlink = 'index.php?option=com_xbbooks&view=book&id='; +$cvlink = 'index.php?option=com_xbbooks&view=category&id='; +$tvlink = 'index.php?option=com_xbbooks&view=tag&id='; + +?> + +
+ header['showheading']) || ($this->header['title'] != '') || ($this->header['text'] != '')) { + echo XbcultureHelper::sitePageheader($this->header); + } ?> + +
+ sidebar)) : ?> +
+ sidebar; ?> +
+
+ +
+ +
+ pagination->total; + echo $fnd .' '. Text::_(($fnd==1)?'XBCULTURE_REVIEW':'XBCULTURE_REVIEWS').' '.Text::_('XBCULTURE_FOUND').', '; + ?> + +
+
+ + $this)); + ?> +
+ searchTitle; ?> + + Searched for '; + if (stripos($search, 'i:') === 0) { + echo trim(substr($search, 2)).' '.Text::_('XBCULTURE_AS_ID'); + } elseif ((stripos($search, 's:') === 0) || (stripos($search, 'r:') === 0)) { + echo trim(substr($search, 2)).' '.Text::_('XBBOOKS_AS_INREV'); + } else { + echo trim($search).' '.Text::_('XBBOOKS_AS_INNAMES'); + } + echo '

'; + } ?> + + items)) : ?> +
+ +
+ + + + + + + + + + + + + + + + + + items)) : ?> + '; + ?> + items as $i => $item) : + ?> + + + + + + + + + + + +
+ + + + + +
+ +
+ + + '. + Text::_( 'XBCULTURE_TAGS_U' ); ?> +
+ pagination->getListFooter(); ?> +
+

+ checked_out) { + $couname = Factory::getUser($item->checked_out)->username; + echo HTMLHelper::_('jgrid.checkedout', $i, Text::_('XBCULTURE_OPENEDBY').': '.$couname, $item->checked_out_time, 'review.', $canCheckin); + } ?> + + title; ?> + +
escape($item->alias));?> +

+

+ by: reviewer; ?> +

+
booktitle == '') : ?> +

Book not found - orphan review

+ +

+ booktitle; ?> + +

+ +
+
+ zero_rating) && ($item->rating==0)) { + echo ''; + } else { + echo str_repeat('⭐',$item->rating); + } + ?> +
+

on: rev_date , 'd M Y'); ?> +

+
+

+ summary)) : ?> + summary; ?> + + + review)) : ?> + : + review,250); ?> + + + + +

+ review)) && (strlen($item->review)>210)) : ?> +

+ review)).' '.Text::_('XBCULTURE_WORDS'); + ?> +

+ + +
+

+ category_title; ?> +

+ + +
+ + + +
+ pagination->getListFooter(); ?> + + + +
+
+

+ + + + + diff --git a/src/com_xbbooks/site/views/bookreviews/tmpl/default.xml b/src/com_xbbooks/site/views/bookreviews/tmpl/default.xml new file mode 100644 index 0000000..87a40b0 --- /dev/null +++ b/src/com_xbbooks/site/views/bookreviews/tmpl/default.xml @@ -0,0 +1,112 @@ + + + + + Displays a list (table) of reviews. Options enable user search & filtering or to restrict to single category and filter by tags. + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + +
+ + +
+ + + +
+
+ +
\ No newline at end of file diff --git a/src/com_xbbooks/site/views/bookreviews/tmpl/index.html b/src/com_xbbooks/site/views/bookreviews/tmpl/index.html new file mode 100644 index 0000000..3af6301 --- /dev/null +++ b/src/com_xbbooks/site/views/bookreviews/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/com_xbbooks/site/views/bookreviews/tmpl/modalpv.php b/src/com_xbbooks/site/views/bookreviews/tmpl/modalpv.php new file mode 100755 index 0000000..118b4fe --- /dev/null +++ b/src/com_xbbooks/site/views/bookreviews/tmpl/modalpv.php @@ -0,0 +1,31 @@ + + + + + diff --git a/src/com_xbbooks/site/views/bookreviews/view.html.php b/src/com_xbbooks/site/views/bookreviews/view.html.php new file mode 100644 index 0000000..0f072db --- /dev/null +++ b/src/com_xbbooks/site/views/bookreviews/view.html.php @@ -0,0 +1,72 @@ +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->searchTitle = $this->state->get('filter.search'); + + $params = $this->state->get('params'); //ComponentHelper::getParams('com_xbbooks'); + $this->zero_rating = $params->get('zero_rating'); + $this->zero_class = $params->get('zero_class'); + $this->stars_class = $params->get('stars_class'); + + $this->header = array(); + $this->header['showheading'] = $this->params->get('show_page_heading',0,'int'); + $this->header['heading'] = $this->params->get('page_heading','','text'); + if ($this->header['heading'] =='') { + $this->header['heading'] = $this->params->get('page_title','','text'); + } + $this->header['title'] = $this->params->get('list_title','','text'); + $this->header['subtitle'] = $this->params->get('list_subtitle','','text'); + $this->header['text'] = $this->params->get('list_headtext','','text'); + + $this->search_bar = $this->params->get('search_bar','','int'); + $this->hide_cat = (!$this->showcat || ($this->params->get('menu_category_id',0)>0)) ? true : false; + $this->hide_tag = (!$this->showtags || (!empty($this->params->get('menu_tag','')))) ? true : false; + + $this->show_pic = $this->params->get('show_bpiccol','1','int'); + $this->show_sum = $this->params->get('show_bsumcol','1','int'); + + // Check for errors. + if (count($errors = $this->get('Errors'))) { + Factory::getApplication()->enqueueMessage(implode('
', $errors),'error'); + return false; + } + + // Display the template + parent::display($tpl); + + // Set the document + $this->setDocument(); + } + + protected function setDocument() + { + $document = Factory::getDocument(); + $document->setTitle(Text::_('xbBooks: Reviews')); + } + +} \ No newline at end of file diff --git a/src/com_xbbooks/xbbooks.xml b/src/com_xbbooks/xbbooks.xml index 1a59120..95d867a 100644 --- a/src/com_xbbooks/xbbooks.xml +++ b/src/com_xbbooks/xbbooks.xml @@ -1,8 +1,8 @@ xbbooks - 22nd January 2023 - 1.0.3.6 + 26th January 2023 + 1.0.3.7 Roger C-O roger@crosborne.uk www.crosborne.uk