Files
JellyPy/plexpy/datatables.py
Tim dd90f2e375 Fix broken search on history tables.
Fix bug in history search which wouldn't search for full title.
Fix bug where user info pages crashes if user no longer in friends list.
Fix bug with query structure, mainly affected incomplete user IP list.
User user id on Top user in home stats.
Add missing Xbox icon.
2015-07-17 21:47:27 +02:00

219 lines
8.6 KiB
Python

# This file is part of PlexPy.
#
# PlexPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PlexPy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
# TODO: Implement with sqlite3 directly instead of using db class
from plexpy import logger, helpers, database
import re
class DataTables(object):
"""
Server side processing for Datatables
"""
def __init__(self):
self.ssp_db = database.MonitorDatabase()
# TODO: Pass all parameters via kwargs
def ssp_query(self, table_name,
columns=[],
start=0,
length=0,
order_column=0,
order_dir='asc',
search_value='',
search_regex='',
custom_where='',
group_by='',
join_type=None,
join_table=None,
join_evals=None,
kwargs=None):
parameters = self.process_kwargs(kwargs)
if group_by != '':
grouping = True
else:
grouping = False
column_data = self.extract_columns(columns)
where = self.construct_where(column_data, search_value, grouping, parameters)
order = self.construct_order(column_data, order_column, order_dir, parameters, table_name, grouping)
join = ''
if join_type:
join_iter = 0
for join_type_item in join_type:
if join_type_item.upper() == 'LEFT OUTER JOIN':
join_item = 'LEFT OUTER JOIN %s ON %s = %s ' % \
(join_table[join_iter], join_evals[join_iter][0], join_evals[join_iter][1])
elif join_type_item.upper() == 'JOIN' or join_type.upper() == 'INNER JOIN':
join_item = 'INNER JOIN %s ON %s = %s ' % \
(join_table[join_iter], join_evals[join_iter][0], join_evals[join_iter][1])
else:
join_item = ''
join_iter += 1
join += join_item
# TODO: custom_where is ugly and causes issues with reported total results
if custom_where != '':
custom_where = 'WHERE (' + custom_where + ')'
if grouping:
if custom_where == '':
query = 'SELECT * FROM (SELECT %s FROM %s %s GROUP BY %s) %s %s' \
% (column_data['column_string'], table_name, join, group_by,
where, order)
else:
query = 'SELECT * FROM (SELECT %s FROM %s %s %s GROUP BY %s) %s %s' \
% (column_data['column_string'], table_name, join, custom_where, group_by,
where, order)
else:
if custom_where == '':
query = 'SELECT %s FROM %s %s %s %s' \
% (column_data['column_string'], table_name, join, where,
order)
else:
query = 'SELECT * FROM (SELECT %s FROM %s %s %s %s) %s' \
% (column_data['column_string'], table_name, join, where,
order, custom_where)
# logger.debug(u"Query string: %s" % query)
filtered = self.ssp_db.select(query)
if search_value == '':
totalcount = len(filtered)
else:
totalcount = self.ssp_db.select('SELECT COUNT(*) from %s' % table_name)[0][0]
result = filtered[start:(start + length)]
output = {'result': result,
'filteredCount': len(filtered),
'totalCount': totalcount}
return output
@staticmethod
def construct_order(column_data, order_column, order_dir, parameters=None, table_name=None, grouped=False):
order = ''
if grouped:
sort_col = column_data['column_named'][order_column]
else:
sort_col = column_data['column_order'][order_column]
if parameters:
for parameter in parameters:
if parameter['data'] != '':
if int(order_column) == parameter['index']:
if parameter['data'] in column_data['column_named'] and parameter['orderable'] == 'true':
if table_name and table_name != '':
order = 'ORDER BY %s COLLATE NOCASE %s' % (sort_col, order_dir)
else:
order = 'ORDER BY %s COLLATE NOCASE %s' % (sort_col, order_dir)
else:
order = 'ORDER BY %s COLLATE NOCASE %s' % (sort_col, order_dir)
return order
@staticmethod
def construct_where(column_data, search_value='', grouping=False, parameters=None):
if search_value != '':
where = 'WHERE '
if parameters:
for column in column_data['column_named']:
search_skip = False
for parameter in parameters:
if column.rpartition('.')[-1] in parameter['data']:
if parameter['searchable'] == 'true':
where += column + ' LIKE "%' + search_value + '%" OR '
search_skip = True
else:
search_skip = True
if not search_skip:
where += column + ' LIKE "%' + search_value + '%" OR '
else:
for column in column_data['column_named']:
where += column + ' LIKE "%' + search_value + '%" OR '
# TODO: This will break the query if all parameters are excluded
where = where[:-4]
return where
else:
where = ''
return where
@staticmethod
def extract_columns(columns=[]):
columns_string = ''
columns_literal = []
columns_named = []
columns_order = []
for column in columns:
columns_string += column
columns_string += ', '
# TODO: make this case insensitive
if ' as ' in column:
columns_literal.append(column.rpartition(' as ')[0])
columns_named.append(column.rpartition(' as ')[-1].rpartition('.')[-1])
columns_order.append(column.rpartition(' as ')[-1])
else:
columns_literal.append(column)
columns_named.append(column.rpartition('.')[-1])
columns_order.append(column)
columns_string = columns_string[:-2]
column_data = {'column_string': columns_string,
'column_literal': columns_literal,
'column_named': columns_named,
'column_order': columns_order
}
return column_data
# TODO: Fix this method. Should not break if kwarg list is not sorted.
def process_kwargs(self, kwargs):
column_parameters = []
for kwarg in sorted(kwargs):
if re.search(r"\[(\w+)\]", kwarg) and kwarg[:7] == 'columns':
parameters = re.findall(r"\[(\w+)\]", kwarg)
array_index = ''
for parameter in parameters:
pass_complete = False
if parameter.isdigit():
array_index = parameter
if parameter == 'data':
data = kwargs.get('columns[' + array_index + '][data]', "")
if parameter == 'orderable':
orderable = kwargs.get('columns[' + array_index + '][orderable]', "")
if parameter == 'searchable':
searchable = kwargs.get('columns[' + array_index + '][searchable]', "")
pass_complete = True
if pass_complete:
row = {'index': int(array_index),
'data': data,
'searchable': searchable,
'orderable': orderable}
column_parameters.append(row)
return sorted(column_parameters, key=lambda i: i['index'])