Merge pull request #1661 from rmehta/link-count

[enhancement] count number of times a link is used and show most popular links on thei top
This commit is contained in:
Rushabh Mehta 2016-03-30 13:16:04 +05:30
commit 61218f7a80
5 changed files with 63 additions and 2 deletions

View file

@ -87,7 +87,7 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0,
filters=filters, fields=fields,
or_filters = or_filters, limit_start = start,
limit_page_length=page_len,
order_by="if(_relevance, _relevance, 99999), modified desc".format(doctype),
order_by="if(_relevance, _relevance, 99999), idx desc, modified desc".format(doctype),
ignore_permissions = True if doctype == "DocType" else False, # for dynamic links
as_list=True)

View file

@ -111,6 +111,7 @@ scheduler_events = {
"frappe.email.doctype.email_account.email_account.pull",
"frappe.email.doctype.email_account.email_account.notify_unreplied",
"frappe.utils.error.collect_error_snapshots",
"frappe.model.utils.link_count.update_link_count",
],
"daily": [
"frappe.email.bulk.clear_outbox",

View file

@ -8,6 +8,7 @@ from frappe.utils import (cint, flt, now, cstr, strip_html, getdate, get_datetim
sanitize_html, sanitize_email)
from frappe.model import default_fields
from frappe.model.naming import set_new_name
from frappe.model.utils.link_count import notify_link_count
from frappe.modules import load_doctype_module
from frappe.model import display_fieldtypes
from frappe.model.db_schema import type_map, varchar_len
@ -403,6 +404,7 @@ class BaseDocument(object):
for df in (self.meta.get_link_fields()
+ self.meta.get("fields", {"fieldtype":"Dynamic Link"})):
docname = self.get(df.fieldname)
if docname:
if df.fieldtype=="Link":
doctype = df.options
@ -420,6 +422,8 @@ class BaseDocument(object):
setattr(self, df.fieldname, value)
notify_link_count(doctype, docname)
if not value:
invalid_links.append((df.fieldname, docname, get_msg(df, docname)))

View file

@ -0,0 +1,29 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
from __future__ import unicode_literals
import frappe
def notify_link_count(doctype, name):
'''updates link count for given document'''
link_count = frappe.cache().get_value('_link_count')
if not link_count:
link_count = {}
if not (doctype, name) in link_count:
link_count[(doctype, name)] = 1
else:
link_count[(doctype, name)] += 1
frappe.cache().set_value('_link_count', link_count)
def update_link_count():
'''increment link count in the `idx` column for the given document'''
link_count = frappe.cache().get_value('_link_count')
if link_count:
for key, count in link_count.iteritems():
frappe.db.sql('update `tab{0}` set idx = idx + %s where name=%s'.format(key[0]), (count, key[1]))
# reset the count
frappe.cache().delete_value('_link_count')

View file

@ -98,7 +98,7 @@ class TestDocument(unittest.TestCase):
def test_permission(self):
frappe.set_user("Guest")
d = self.assertRaises(frappe.PermissionError, self.test_insert)
self.assertRaises(frappe.PermissionError, self.test_insert)
frappe.set_user("Administrator")
def test_permission_single(self):
@ -189,3 +189,30 @@ class TestDocument(unittest.TestCase):
self.assertTrue(xss not in d.subject)
self.assertTrue(escaped_xss in d.subject)
def test_link_count(self):
from frappe.model.utils.link_count import update_link_count
update_link_count()
doctype, name = 'User', 'test@example.com'
d = self.test_insert()
d.ref_type = doctype
d.ref_name = name
link_count = frappe.cache().get_value('_link_count') or {}
old_count = link_count.get((doctype, name)) or 0
d.save()
link_count = frappe.cache().get_value('_link_count') or {}
new_count = link_count.get((doctype, name)) or 0
self.assertEquals(old_count + 1, new_count)
before_update = frappe.db.get_value(doctype, name, 'idx')
update_link_count()
after_update = frappe.db.get_value(doctype, name, 'idx')
self.assertEquals(before_update + new_count, after_update)