1 /** 2 * Copyright © DiamondMVC 2019 3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE) 4 * Author: Jacob Jensen (bausshf) 5 */ 6 module diamond.core.filterservice; 7 8 private 9 { 10 /// The entries that can be searched. 11 __gshared FilterEntry[] _entries; 12 13 /// A filter entry. 14 final class FilterEntry 15 { 16 /// The title. 17 string title; 18 /// The url. 19 string url; 20 /// The keywords. 21 string[] keywords; 22 /// The keyword replacement. 23 string keywordReplacement; 24 25 final: 26 /** 27 * Creates a new filter entry. 28 * Params: 29 * title = The title. 30 * url = The url. 31 * keywords = The keywords. 32 * keywordReplacement = The keyword replacement. 33 */ 34 this(string title, string url, string[] keywords, string keywordReplacement) 35 { 36 this.title = title; 37 this.url = url; 38 this.keywords = keywords; 39 this.keywordReplacement = keywordReplacement; 40 } 41 } 42 } 43 44 /// A filter result. 45 final class FilterResult 46 { 47 private: 48 /// The title. 49 string _title; 50 /// The url. 51 string _url; 52 53 /** 54 * Creates a new filter result. 55 * Params: 56 * title = The title of the result. 57 * url = The url of the result. 58 */ 59 this(string title, string url) 60 { 61 _title = title; 62 _url = url; 63 } 64 65 public: 66 final: 67 /// Gets the title. 68 string title() { return _title; } 69 70 /// Gets the url. 71 string url() { return _url; } 72 } 73 74 /** 75 * Adds a search filter. 76 * Params: 77 * title = The title of the result. 78 * url = The url of the result. 79 * keywords = The keywords to partially match when searching for the result. 80 * keywordReplacement = A string to replace in the url with the keywords searched. 81 */ 82 void addSearchFilter(string title, string url, string[] keywords, string keywordReplacement = null) 83 { 84 import diamond.errors.checks : enforce; 85 86 enforce(title && title.length, "Missing title."); 87 enforce(url && url.length, "Missing url."); 88 enforce(keywords && keywords.length, "Missing keywords."); 89 90 _entries ~= new FilterEntry(title, url, keywords, keywordReplacement); 91 } 92 93 /** 94 * Gets all filtered results based on a set of keywords. 95 * Params: 96 * searchKeywords = The keywords to search for. 97 * Returns: 98 * An array of the filtered results that matches the keywords partially. 99 */ 100 FilterResult[] search(string[] searchKeywords) 101 { 102 import std.algorithm : canFind; 103 import std.array : join, replace; 104 105 FilterResult[] results; 106 107 if (!_entries) 108 { 109 return results; 110 } 111 112 foreach (entry; _entries) 113 { 114 foreach (searchKeyword; searchKeywords) 115 { 116 bool foundKeyword; 117 118 foreach (keyword; entry.keywords) 119 { 120 if (keyword.canFind(searchKeyword)) 121 { 122 string url = entry.url; 123 124 if (entry.keywordReplacement && entry.keywordReplacement.length) 125 { 126 url = url.replace(entry.keywordReplacement, searchKeywords.join(",")); 127 } 128 129 results ~= new FilterResult(entry.title, url); 130 foundKeyword = true; 131 break; 132 } 133 } 134 135 if (foundKeyword) 136 { 137 break; 138 } 139 } 140 } 141 142 return results; 143 }